标签:exception not finish his art with exec 线程 bottom
线程共有五种状态.分别是: (1)新建 (2)就绪 (3)运行 (4)阻塞 (5)死亡 ,下面列列举的状态需要结合状态示意图更好理解.
下面为线程的状态示意图:
后面两个Object 方法
wait 方法不是一回事,下面的wait方法会一直阻塞在那里),使用场景是例如某个操作执行前需要执行一个加载资源的
任务,那么执行的这个操作就要一直等待加载的操作完成以后才可以执行(join(0)).
object 中的方法,而不是线程中的方法,同时调用 XX.wait(); 时必须要在同步语句中,或是该对象已经被加锁的情况
下,试想一下,wait 方法本身就是某个对象加锁后释放锁,不可能没加锁的情况下可以释放锁.wait 不能自动唤醒,需要
notify / notifyAll 方法
join的源码实现
public final synchronized void join(long millis) throws InterruptedException { long base = System.currentTimeMillis(); long now = 0; if (millis < 0) { throw new IllegalArgumentException("timeout value is negative"); } if (millis == 0) { while (isAlive()) { wait(0); } } else { while (isAlive()) { long delay = millis - now; if (delay <= 0) { break; } wait(delay); now = System.currentTimeMillis() – base; } } }
但是有个问题一直没搞明白,就是源码中的wait方法,要是Object.wait方法,那么它会释放锁,然后其他线程可以获取锁,执行其他线程的动作,但是在join的源码实现中即使是一直循环,按道理是会释放锁的,其他线程可以执行的,但是事实却不是,如下代码,至今未懂.
Thread thread1 = new Thread(() -> { System.out.println("t1 开始执行" + new Date()); synchronized (obj) { try { Thread.currentThread().join(0); //obj.wait(); System.out.println("线程1 继续执行,执行完毕"); } catch (InterruptedException e) { e.printStackTrace(); } } }); Thread thread2 = new Thread(() -> { try { synchronized (obj) { System.out.println("线程2 开始执行 " + new Date()); Thread.sleep(2 * 1000); System.out.println("线程2 执行结束 " + new Date()); // obj.notifyAll(); } } catch (InterruptedException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } }); thread1.start(); Thread.sleep(4*1000); thread2.start();
执行后会发现线程一调用join()方法后,线程2没能获取对象执行,而是等待线程1执行完成后,线程2才会执行.
我们来看看在 Java 7 Concurrency Cookbook 中相关的描述(很清楚地说明了 join() 的作用):
Waiting for the finalization of a thread
In some situations, we will have to wait for the finalization of a thread. For example, we may have a program that will begin initializing the resources it needs before proceeding with the rest of the execution. We can run the initialization tasks as threads and wait for its finalization before continuing with the rest of the program. For this purpose, we can use the join() method of the Thread class. When we call this method using a thread object, it suspends the execution of the calling thread until the object called finishes its execution.
当我们调用某个线程的这个方法时,这个方法会挂起调用线程,直到被调用线程结束执行,调用线程才会继续执行。
可以看到 notify 方法的使用,是在同步方法内,并且同样获取同样的锁对象, wait 和 notify 方法的运用常常被用来做生产者-消费者的实现.
//以下代码来自参考文章,见参考资料 public class Test { public static Object object = new Object(); public static void main(String[] args) { Thread1 thread1 = new Thread1(); Thread2 thread2 = new Thread2(); thread1.start(); try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } thread2.start(); } static class Thread1 extends Thread{ @Override public void run() { synchronized (object) { try { object.wait(); } catch (InterruptedException e) { } System.out.println("线程"+Thread.currentThread().getName()+"获取到了锁"); } } } static class Thread2 extends Thread{ @Override public void run() { synchronized (object) { object.notify(); System.out.println("线程"+Thread.currentThread().getName()+"调用了object.notify()"); } System.out.println("线程"+Thread.currentThread().getName()+"释放了锁"); } } }
下面代码中parent线程会等待child线程执行完成后再继续执行.
// 父线程 public class Parent extends Thread { public void run() { Child child = new Child(); child.start(); child.join(); // ... } }
// 子线程 public class Child extends Thread { public void run() { // ... } }
public class YieldExcemple { public static void main(String[] args) { Thread threada = new ThreadA(); Thread threadb = new ThreadB(); // 设置优先级:MIN_PRIORITY最低优先级1;NORM_PRIORITY普通优先级5;MAX_PRIORITY最高优先级10 threada.setPriority(Thread.MIN_PRIORITY); threadb.setPriority(Thread.MAX_PRIORITY); threada.start(); threadb.start(); } } class ThreadA extends Thread { public void run() { for (int i = 0; i < 10; i++) { System.out.println("ThreadA--" + i); Thread.yield(); } } } class ThreadB extends Thread { public void run() { for (int i = 0; i < 10; i++) { System.out.println("ThreadB--" + i); Thread.yield(); } } }
以下总结来自参考文章.
Java线程中的Thread.yield( )方法,译为线程让步。顾名思义,就是说当一个线程使用了这个方法之后,它就会把自己CPU执行的时间让掉,让自己或者其它的线程运行,注意是让自己或者其他线程运行,并不是单纯的让给其他线程。
yield()的作用是让步。它能让当前线程由“运行状态”进入到“就绪状态”,从而让其它具有相同优先级的等待线程获取执行权;但是,并不能保证在当前线程调用yield()之后,其它具有相同优先级的线程就一定能获得执行权;也有可能是当前线程又进入到“运行状态”继续运行!
举个例子:一帮朋友在排队上公交车,轮到Yield的时候,他突然说:我不想先上去了,咱们大家来竞赛上公交车。然后所有人就一块冲向公交车,
有可能是其他人先上车了,也有可能是Yield先上车了。
但是线程是有优先级的,优先级越高的人,就一定能第一个上车吗?这是不一定的,优先级高的人仅仅只是第一个上车的概率大了一点而已,
最终第一个上车的,也有可能是优先级最低的人。并且所谓的优先级执行,是在大量执行次数中才能体现出来的。
标签:exception not finish his art with exec 线程 bottom
原文地址:https://www.cnblogs.com/Benjious/p/10053610.html