1、 思考题
a、sleep和wait的差别
答:1)最主要是sleep方法没有释放锁,而wait方法释放了锁,使得其他线程可以使用同步控制块或者方法(锁代码块和方法锁)。
2)wait是Object方法,sleep是Thread特有的方法
b、为什么说线程启动后不一定会立刻执行
答:需要等待CPU的调度,如果CPU没有空闲内核,那线程将等待执行。等待(state = osthread->get_state()) == ALLOCATED
c、使用wait和notify的时候 需要有做些什么
答:必须在同步方法中使用wait和notify,因为执行wait和notify的前提条件是必须持有同步方法的monitor的所有权,运行下面任何一个方法都会抛出非法monitor状态异常IllegalMonitorStateException
2、线程有哪些方法
1)currentThread 获取当前线程
2)isAlive 是否存活
3)sleep 暂停当前线程执行
4)getId 获取当前线程的唯一标识
5)interrupt 终止当前线程执行
6)this.interrupted 判断当前线程是否中断,具有清楚中断状态的作用
7)this.isInterrupted 判断Thread线程是否中断
8)suspend/resume 暂停和恢复线程
8)yield 放弃当前cpu资源,将它让给其他任务
9)setPriority 设置线程执行的优先级 1-10
10)join 方法只会使主线程(或者说调用t.join()的线程)进入等待池并等待t线程执行完毕后才会被唤醒。并不影响同一时刻处在运行状态的其他线程。
3、线程的状态转换
4、课后作业
1、给一个文件文件里面有10万条记录每一行是一个0-100000之间的随机数 我们通过启动一个线程 来统计下这个文件里面大于 80000 数字有多少个。 并统计下耗时
public static void main(String[] args) {
List<Integer> data = getData();
Thread t1 = new Thread(new Runnable(){
@Override
public void run() {
System.out.println("开始统计......");
long start= System.currentTimeMillis();
Integer count = 0;
for (Integer item : data) {
if (item >= 80000) {
count ++;
}
}
long end =System.currentTimeMillis();
System.out.println("统计结束,耗时:" + (end-start) + "毫秒");
System.out.println("统计结果count=" +count);
}
});
t1.start();
}
/**
* 获取 10万个0-100000之间的随机数
* @author yy.xiong
**/
private static List<Integer> getData(){
Integer min = 0;
Integer max = 100000;
List<Integer> data = Lists.newArrayList();
for (int i=1; i<=100000; i++){
int item = (int)(min+Math.random()*max);
data.add(item);
}
return data;
}
// 执行结果:
开始统计......
统计结束,耗时:5毫秒
统计结果count=20056
Process finished with exit code 0
2、用wait和notify 的例子 启动两个线程 :1号线程 打印【 步骤1】 然后进入等待 等待结束打印 【步骤4】 2 号线程打印【 步骤2】 然后sleep 3秒 然后打印【 步骤3】然后唤醒1号线程
private static Object target = new Object();
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
synchronized (target) {
step1();
try {
target.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
step4();
}
});
Thread t2 = new Thread(() -> {
synchronized (target) {
step2();
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
step3();
target.notify();
}
});
t1.start();
t2.start();
}
private static void step1(){
System.out.println("这里是步骤1");
}
private static void step2(){
System.out.println("这里是步骤2");
}
private static void step3(){
System.out.println("这里是步骤3");
}
private static void step4(){
System.out.println("这里是步骤4");
}
// 执行结果
这里是步骤1
这里是步骤2
这里是步骤3
这里是步骤4
Process finished with exit code 0
5、课后思考
Java Thread类中的threadStatus是什么时候变更的?如下:
if (threadStatus != 0)
throw new IllegalThreadStateException();
我们先看下Java->操作系统,是如何创建并执行一个线程的,如下图
在jvm层,调用os创建线程代码如下,由此可见,是在jvm创建os线程前,变更了threadStatus值
void Thread::start(Thread* thread) {
trace("start", thread);
if (!DisableStartThread) {
if (thread->is_Java_thread()) {
java_lang_Thread::set_thread_status(((JavaThread*)thread)->threadObj(),
java_lang_Thread::RUNNABLE);
}
// 不同的 OS 会有不同的启动代码逻辑
os::start_thread(thread);
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。