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);
  }
}


断水流大师兄
6 声望0 粉丝