一:sleep(3000);方法和object.wait(10000);区别
1.obj.wait方法会释放锁 必须在sychronized获取到该obj锁的状态下调用obj.wait方法,是Object的方法
2.sleep方法不会释放锁,不用在sychronized获取锁时调用,可以在任何地方使用,是Thread类的方法
sleep,wait调用后都会暂停当前线程并让出cpu的执行时间,但不同的是sleep不会释放当前持有的对象的锁资源,到时间后会继续执行,而wait会放弃所有锁并需要notify/notifyAll后重新获取到对象锁资源后才能继续执行;
Thread.sleep(10000);是静态方法
obj.wait是实例方法;
它们都可以被interrupted方法中断。
Thread.Sleep(1000) 意思是在未来的1000毫秒内本线程不参与CPU竞争,1000毫秒过去之后,这时候也许另外一个线程正在使用CPU,那么这时候操作系统是不会重新分配CPU的,直到那个线程挂起或结束,即使这个时候恰巧轮到操作系统进行CPU 分配,那么当前线程也不一定就是总优先级最高的那个,CPU还是可能被其他线程抢占去。另外值得一提的是Thread.Sleep(0)的作用,就是触发操作系统立刻重新进行一次CPU竞争,竞争的结果也许是当前线程仍然获得CPU控制权,也许会换成别的线程获得CPU控制权。
wait(1000)表示将锁释放1000毫秒,到时间后如果锁没有被其他线程占用,则再次得到锁,然后wait方法结束,执行后面的代码,如果锁被其他线程占用,则等待其他线程释放锁。注意,设置了超时时间的wait方法一旦过了超时时间,并不需要其他线程执行notify也能自动解除阻塞,但是如果没设置超时时间的wait方法必须等待其他线程执行notify。
二:join方法:
用处1:Thread.join方法可以让多线程按照指定的顺序执行
1.测试代码:
class ThreadTest2 extends Thread{
private int I ;
// 上一个线程
private Thread previousThread;
public ThreadTest2(int i, Thread previousThread) {
this.i = I;
this.previousThread = previousThread;
}
@Override
public void run() {
super.run();
// 先注释掉join代码
// try {
// previousThread.join();
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
System.out.println("num:"+i);
}
public static void main(String[] args) {
Thread previousThread = Thread.currentThread();
for (int i = 0;i < 10;i++){
ThreadTest2 threadTest2 = new ThreadTest2(i,previousThread);
threadTest2.start();
previousThread = threadTest2;
}
}
}
如上代码注释掉join代码运行一遍,输出结果:
把注释掉的join代码放开,运行结果如下:
运行的结果按照递增的顺序展示出来
在子线程ThreadTest2中调用previousThread.join();会阻塞调用该方法的线程,直到线程previousThread结束,此线程再继续
Thread类中的join方法源码:
/**
* Waits at most {@code millis} milliseconds for this thread to
* die. A timeout of {@code 0} means to wait forever.
*
* 等待最多{@code millis}毫秒这个线程死亡。{@code 0}的超时意味着永远等待。
*
* <p> This implementation uses a loop of {@code this.wait} calls
* conditioned on {@code this.isAlive}. As a thread terminates the
* {@code this.notifyAll} method is invoked. It is recommended that
* applications not use {@code wait}, {@code notify}, or
* {@code notifyAll} on {@code Thread} instances.
*
* @param millis
* the time to wait in milliseconds
*
* @throws IllegalArgumentException
* if the value of {@code millis} is negative
*
* @throws InterruptedException
* if any thread has interrupted the current thread. The
* <i>interrupted status</i> of the current thread is
* cleared when this exception is thrown.
*/
public final void join(long millis) throws InterruptedException {
synchronized(lock) {
long base = System.currentTimeMillis();
long now = 0;
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (millis == 0) {
while (isAlive()) {
lock.wait(0);
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
lock.wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
}
源码分析:synchronized(lock) 中的lock是谁,有的说是privirousThread线程,lock.wait(0);等待的就是privirousThread线程对象,又说这个对象在privirousThread在自己线程是持有的,等privirousThread线程结束时会notifyAll所有这个锁的等待的线程,那怎么进去synchronized(lock)的?????
三:yeild 放弃,让出
源码:
/**
* A hint to the scheduler that the current thread is willing to yield
* its current use of a processor. The scheduler is free to ignore this
* hint.
* 提示调度程序当前线程愿意放弃当前对处理器的使用。调度器可以忽略这个提示。
*
* <p> Yield is a heuristic attempt to improve relative progression
* between threads that would otherwise over-utilise a CPU. Its use
* should be combined with detailed profiling and benchmarking to
* ensure that it actually has the desired effect.
*
* <p> It is rarely appropriate to use this method. It may be useful
* for debugging or testing purposes, where it may help to reproduce
* bugs due to race conditions. It may also be useful when designing
* concurrency control constructs such as the ones in the
* {@link java.util.concurrent.locks} package.
*/
public static native void yield();
yield()的作用是让步。它能让当前线程由“运行状态”进入到“就绪状态”,从而让其它具有相同优先级的等待线程获取执行权;但是,并不能保证在当前线程调用yield()之后,其它具有相同优先级的线程就一定能获得执行权;也有可能是当前线程又进入到“运行状态”继续运行!
举个例子:一帮朋友在排队上公交车,轮到Yield的时候,他突然说:我不想先上去了,咱们大家来竞赛上公交车。然后所有人就一块冲向公交车,有可能是其他人先上车了,也有可能是Yield先上车了。
但是线程是有优先级的,优先级越高的人,就一定能第一个上车吗?这是不一定的,优先级高的人仅仅只是第一个上车的概率大了一点而已,
最终第一个上车的,也有可能是优先级最低的人。并且所谓的优先级执行,是在大量执行次数中才能体现出来的。
测试代码参考:
https://www.cnblogs.com/java-spring/p/8309931.html