/*
sleep()方法使当前线程放弃CPU使用权,但是不释放已抢占对象的锁,当前线程阻塞。其他线程可以抢占cpu使用权,但无法抢占对象的锁。sleep 方法允许较低优先级的线程获得运行机会
sleep()方法是Thread类的静态方法
Thread.sleep(2000);线程休眠2秒
thread.interrupt();可以终止线程的阻塞,并抛出InterruptedException异常,捕获异常后,线程可以继续运行
*/
/*
wait()方法使当前线程放弃CPU使用权,并且释放已抢占对象的锁,当前线程阻塞。其他线程可以抢占cpu使用权,并且抢占对象的锁。
o.notify();可以唤醒1个被o.wait();阻塞的线程
o.notifyAll();可以唤醒所有被o.wait();阻塞的线程
o.wait();线程等待
o.wait(2000);线程等待2秒
thread.interrupt();可以终止线程的阻塞,并抛出InterruptedException异常,捕获异常后,线程可以继续运行
*/
/*
join()方法,thread2.join()使当前线程放弃CPU使用权,并且释放已抢占对象的锁,等待thread2线程执行完毕后,当前线程继续运行。
thread.interrupt();可以终止线程的阻塞,并抛出InterruptedException异常,捕获异常后,线程可以继续运行
*/
/*
yield()方法,Thread.yield()使当前线程放弃CPU使用权,然后当前线程和与当前线程优先级相同的线程竞争抢占cpu使用权,如果没有和当前线程优先级相同的线程,则当前线程继续获得cpu使用权,继续执行。
yield()使当前线程放弃CPU使用权,但是不释放已抢占对象的锁,所以yield()方法要在synchronized代码块外使用才有效果。
在线程数量小于cpu核心数的情况下,不存在cpu使用权的竞争,只有在线程数量多于cpu核心数的情况下才存在CPU使用权的竞争,此时yield()方法才会有效果。
*/
wait():
有3个线程抢占o对象的锁,并分别对aa、bb、cc进行++操作,但是aa、bb、cc两两相差不能超过2
public class Main3 {
static Object o = new Object();
static Integer aa = 0;
static Integer bb = 0;
static Integer cc = 0;
public static void main(String[] args) {
Runnable runnableA = new Runnable() {
@Override
public void run() {
String name = Thread.currentThread().getName();
System.out.println(name + " 线程正在运行");
synchronized (o) {
while (aa < 4) {
if (aa-bb >= 2 || aa-cc >= 2) {
try {
System.out.println(name + " 线程放弃CPU使用权,并且放弃o对象的锁,当前线程阻塞,阻塞之前唤醒其他等待的线程");
o.notifyAll();
o.wait();
} catch (InterruptedException e) {
System.out.println(name + " 线程阻塞被终止,进入就绪状态");
}
} else {
aa++;
for (int i = 1; i <= 2100000000; i++) {
if (i == 2100000000) {
System.out.println(name+" 线程完成了 "+aa+" 次伟大的循环,aa="+aa+",bb="+bb+",cc="+cc);
}
}
}
}
//退出之前唤醒其他等待的线程
o.notifyAll();
}
System.out.println(name + " 线程完成任务");
}
};
Runnable runnableB = new Runnable() {
@Override
public void run() {
String name = Thread.currentThread().getName();
System.out.println(name + " 线程正在运行");
synchronized (o) {
while (bb < 4) {
if (bb-aa >= 2 || bb-cc >= 2) {
try {
System.out.println(name + " 线程放弃CPU使用权,并且放弃o对象的锁,当前线程阻塞,阻塞之前唤醒其他等待的线程");
o.notifyAll();
o.wait();
} catch (InterruptedException e) {
System.out.println(name + " 线程阻塞被终止,进入就绪状态");
}
} else {
bb++;
for (int i = 1; i <= 2100000000; i++) {
if (i == 2100000000) {
System.out.println(name+" 线程完成了 "+bb+" 次伟大的循环,aa="+aa+",bb="+bb+",cc="+cc);
}
}
}
}
//退出之前唤醒其他等待的线程
o.notifyAll();
}
System.out.println(name + " 线程完成任务");
}
};
Runnable runnableC = new Runnable() {
@Override
public void run() {
String name = Thread.currentThread().getName();
System.out.println(name + " 线程正在运行");
synchronized (o) {
while (cc < 4) {
if (cc-bb >= 2 || cc-aa >= 2) {
try {
System.out.println(name + " 线程放弃CPU使用权,并且放弃o对象的锁,当前线程阻塞,阻塞之前唤醒其他等待的线程");
o.notifyAll();
o.wait();
} catch (InterruptedException e) {
System.out.println(name + " 线程阻塞被终止,进入就绪状态");
}
} else {
cc++;
for (int i = 1; i <= 2100000000; i++) {
if (i == 2100000000) {
System.out.println(name+" 线程完成了 "+cc+" 次伟大的循环,aa="+aa+",bb="+bb+",cc="+cc);
}
}
}
}
//退出之前唤醒其他等待的线程
o.notifyAll();
}
System.out.println(name + " 线程完成任务");
}
};
Thread thread1 = new Thread(runnableA);
Thread thread2 = new Thread(runnableB);
Thread thread3 = new Thread(runnableC);
thread1.start();
thread2.start();
thread3.start();
}
运行结果:wait()方法使当前线程放弃CPU使用权,并且释放已抢占对象的锁,其他线程可以抢占cpu使用权,并签章对象的锁。
Thread-0 线程正在运行
Thread-2 线程正在运行
Thread-1 线程正在运行
Thread-0 线程完成了 1 次伟大的循环,aa=1,bb=0,cc=0
Thread-0 线程完成了 2 次伟大的循环,aa=2,bb=0,cc=0
Thread-0 线程放弃CPU使用权,并且放弃o对象的锁,当前线程阻塞,阻塞之前唤醒其他等待的线程
Thread-1 线程完成了 1 次伟大的循环,aa=2,bb=1,cc=0
Thread-1 线程完成了 2 次伟大的循环,aa=2,bb=2,cc=0
Thread-1 线程放弃CPU使用权,并且放弃o对象的锁,当前线程阻塞,阻塞之前唤醒其他等待的线程
Thread-2 线程完成了 1 次伟大的循环,aa=2,bb=2,cc=1
Thread-2 线程完成了 2 次伟大的循环,aa=2,bb=2,cc=2
Thread-2 线程完成了 3 次伟大的循环,aa=2,bb=2,cc=3
Thread-2 线程完成了 4 次伟大的循环,aa=2,bb=2,cc=4
Thread-2 线程完成任务
Thread-1 线程完成了 3 次伟大的循环,aa=2,bb=3,cc=4
Thread-1 线程完成了 4 次伟大的循环,aa=2,bb=4,cc=4
Thread-1 线程完成任务
Thread-0 线程完成了 3 次伟大的循环,aa=3,bb=4,cc=4
Thread-0 线程完成了 4 次伟大的循环,aa=4,bb=4,cc=4
Thread-0 线程完成任务
sleep():
有3个线程抢占o对象的锁,并分别对aa、bb、cc进行++操作,但是aa、bb、cc两两相差不能超过2
public class Main4 {
static Object o = new Object();
static Integer aa = 0;
static Integer bb = 0;
static Integer cc = 0;
public static void main(String[] args) {
Runnable runnableA = new Runnable() {
@Override
public void run() {
String name = Thread.currentThread().getName();
System.out.println(name + " 线程正在运行");
synchronized (o) {
while (aa < 4) {
if (aa-bb >= 2 || aa-cc >= 2) {
try {
System.out.println(name + " 线程放弃CPU使用权,但是不放弃对象的锁,当前线程阻塞,其他线程无法获得对象的锁");
Thread.sleep(4000);
} catch (InterruptedException e) {
System.out.println(name + " 线程阻塞被终止,进入就绪状态");
}
} else {
aa++;
for (int i = 1; i <= 2100000000; i++) {
if (i == 2100000000) {
System.out.println(name+" 线程完成了 "+aa+" 次伟大的循环,aa="+aa+",bb="+bb+",cc="+cc);
}
}
}
}
}
System.out.println(name + " 线程完成任务");
}
};
Runnable runnableB = new Runnable() {
@Override
public void run() {
String name = Thread.currentThread().getName();
System.out.println(name + " 线程正在运行");
synchronized (o) {
while (bb < 4) {
if (bb-aa >= 2 || bb-cc >= 2) {
try {
System.out.println(name + " 线程放弃CPU使用权,但是不放弃对象的锁,当前线程阻塞,其他线程无法获得对象的锁");
Thread.sleep(4000);
} catch (InterruptedException e) {
System.out.println(name + " 线程阻塞被终止,进入就绪状态");
}
} else {
bb++;
for (int i = 1; i <= 2100000000; i++) {
if (i == 2100000000) {
System.out.println(name+" 线程完成了 "+bb+" 次伟大的循环,aa="+aa+",bb="+bb+",cc="+cc);
}
}
}
}
}
System.out.println(name + " 线程完成任务");
}
};
Runnable runnableC = new Runnable() {
@Override
public void run() {
String name = Thread.currentThread().getName();
System.out.println(name + " 线程正在运行");
synchronized (o) {
while (cc < 4) {
if (cc-bb >= 2 || cc-aa >= 2) {
try {
System.out.println(name + " 线程放弃CPU使用权,但是不放弃对象的锁,当前线程阻塞,其他线程无法获得对象的锁");
Thread.sleep(4000);
} catch (InterruptedException e) {
System.out.println(name + " 线程阻塞被终止,进入就绪状态");
}
} else {
cc++;
for (int i = 1; i <= 2100000000; i++) {
if (i == 2100000000) {
System.out.println(name+" 线程完成了 "+cc+" 次伟大的循环,aa="+aa+",bb="+bb+",cc="+cc);
}
}
}
}
}
System.out.println(name + " 线程完成任务");
}
};
Thread thread1 = new Thread(runnableA);
Thread thread2 = new Thread(runnableB);
Thread thread3 = new Thread(runnableC);
thread1.start();
thread2.start();
thread3.start();
}
运行结果:由于sleep()不会使线程放弃对象的锁,所以获得锁的线程将无限循环。
Thread-1 线程正在运行
Thread-0 线程正在运行
Thread-2 线程正在运行
Thread-1 线程完成了 1 次伟大的循环,aa=0,bb=1,cc=0
Thread-1 线程完成了 2 次伟大的循环,aa=0,bb=2,cc=0
Thread-1 线程放弃CPU使用权,当前线程阻塞
Thread-1 线程放弃CPU使用权,当前线程阻塞
Thread-1 线程放弃CPU使用权,当前线程阻塞
Thread-1 线程放弃CPU使用权,当前线程阻塞
Thread-1 线程放弃CPU使用权,当前线程阻塞
。。。。。。
join():
主线程和子线程分别执行10次伟大的循环,但是主线程比较懒,想等子线程执行完毕后再执行,子线程执行两次后感觉太累,想找个作伴的,于是把主线程喊醒了,两个线程一起执行。
public static void main(String[] args) {
Thread mainThread = Thread.currentThread();
Runnable runnable = new Runnable() {
@Override
public void run() {
String name = Thread.currentThread().getName();
System.out.println(name + " 线程 开始 执行");
int j = 1;
for (; j <= 2; j++) {
for (int i = 0; i < 2100000000; i++) {
if (i == 0) {
System.out.println(name + " 线程完成 " + j + " 次伟大的循环");
}
}
}
System.out.println("太累了,主线程你快起来,抓紧时间干活。");
mainThread.interrupt();
for (; j <= 10; j++) {
for (int i = 0; i < 2100000000; i++) {
if (i == 0) {
System.out.println(name + " 线程完成 " + j + " 次伟大的循环");
}
}
}
System.out.println(name + " 线程执行完毕");
}
};
Thread thread1 = new Thread(runnable, "thread1");
thread1.start();
try {
System.out.println("我是主线程,我先休息会,等thread1 线程执行完我再执行。");
thread1.join();
} catch (InterruptedException e) {
System.out.println("主线程还没休息够就被终止休息了,继续干活。");
}
for (int k = 1; k <= 10; k++) {
for (int i = 0; i < 2100000000; i++) {
if (i == 0) {
System.out.println("主线程完成 " + k + " 次伟大的循环");
}
}
}
System.out.println("主线程执行完毕");
}
运行结果:
我是主线程,我先休息会,等thread1 线程执行完我再执行。
thread1 线程 开始 执行
thread1 线程完成 1 次伟大的循环
thread1 线程完成 2 次伟大的循环
太累了,主线程你快起来,抓紧时间干活。
主线程还没休息够就被终止休息了,继续干活。
thread1 线程完成 3 次伟大的循环
主线程完成 1 次伟大的循环
主线程完成 2 次伟大的循环
主线程完成 3 次伟大的循环
thread1 线程完成 4 次伟大的循环
主线程完成 4 次伟大的循环
thread1 线程完成 5 次伟大的循环
主线程完成 5 次伟大的循环
thread1 线程完成 6 次伟大的循环
主线程完成 6 次伟大的循环
thread1 线程完成 7 次伟大的循环
thread1 线程完成 8 次伟大的循环
主线程完成 7 次伟大的循环
主线程完成 8 次伟大的循环
thread1 线程完成 9 次伟大的循环
主线程完成 9 次伟大的循环
thread1 线程完成 10 次伟大的循环
主线程完成 10 次伟大的循环
thread1 线程执行完毕
主线程执行完毕
yield():
public static void main(String[] args) {
Object o = new Object();
CountDownLatch co = new CountDownLatch(1);
Runnable runnable = new Runnable() {
@Override
public void run() {
String name = Thread.currentThread().getName();
System.out.println(name + " 线程 开始 执行");
try {
co.await();
} catch (InterruptedException e) {
}
int j = 1;
synchronized (o) {
for (; j <= 2; j++) {
for (int i = 0; i < 2100000000; i++) {
if (i == 0) {
System.out.println(name + " 线程完成 " + j + " 次伟大的循环");
}
}
}
System.out.println(name + " 线程让步");
// 线程让步,但不释放锁,所以线程还会获得cup执行权继续执行。
Thread.yield();
for (; j <= 6; j++) {
for (int i = 0; i < 2100000000; i++) {
if (i == 0) {
System.out.println(name + " 线程完成 " + j + " 次伟大的循环");
}
}
}
}
System.out.println(name + " 线程让步");
// 线程让步,此时没有锁,然后当前线程会和同等优先级的线程共同竞争CPU使用权。
// 在线程数量小于cpu核心数的情况下,不存在cpu使用权的竞争,在线程数量多余cpu核心数的情况下才存在CPU使用权的竞争。
Thread.yield();
synchronized (o) {
for (; j <= 10; j++) {
for (int i = 0; i < 2100000000; i++) {
if (i == 0) {
System.out.println(name + " 线程完成 " + j + " 次伟大的循环");
}
}
}
}
}
};
Thread thread1 = new Thread(runnable, "thread1");
Thread thread2 = new Thread(runnable, "thread2");
Thread thread3 = new Thread(runnable, "thread3");
Thread thread4 = new Thread(runnable, "thread4");
// 优先级高只是获得cpu使用权的几率高而已,并不代表优先级高的线程要先执行。
thread1.setPriority(Thread.MIN_PRIORITY);
thread2.setPriority(Thread.NORM_PRIORITY);
thread3.setPriority(Thread.NORM_PRIORITY);
thread4.setPriority(Thread.MAX_PRIORITY);
thread1.start();
thread2.start();
thread3.start();
thread4.start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
co.countDown();
}