-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
286ceae
commit 61f7521
Showing
7 changed files
with
418 additions
and
0 deletions.
There are no files selected for viewing
19 changes: 19 additions & 0 deletions
19
basejava/src/main/java/com/study/basejava/a1_thread_status/Demo1.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package com.study.basejava.a1_thread_status; | ||
|
||
/** | ||
* 示例1 - JAVA程序执行分析 | ||
*/ | ||
public class Demo1 { | ||
public int x; | ||
public int sum (int a, int b){ | ||
return a + b ; | ||
} | ||
|
||
public static void main(String[] args) { | ||
Demo1 demo1 = new Demo1(); | ||
demo1.x = 3; | ||
int y = 3; | ||
int z = demo1.sum(demo1.x,y); | ||
System.out.println("person age is " + z); | ||
} | ||
} |
87 changes: 87 additions & 0 deletions
87
basejava/src/main/java/com/study/basejava/a1_thread_status/Demo2.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
package com.study.basejava.a1_thread_status; | ||
|
||
/** | ||
* 示例2 - 多线程运行状态切换示例 | ||
*/ | ||
public class Demo2 { | ||
public static Thread thread1; | ||
public static Demo2 obj; | ||
|
||
public static void main(String[] args) throws InterruptedException { | ||
// 第一种状态切换 - 新建 -> 运行 -> 终止 | ||
threadRunTimeStatus1(); | ||
System.out.println(); | ||
System.out.println("-----------------"); | ||
System.out.println(); | ||
// 第二种状态切换 - 新建 -> 运行 -> 等待 -> 运行 -> 终止(sleep方式) | ||
threadRunTimeStatus2(); | ||
System.out.println(); | ||
System.out.println("-----------------"); | ||
System.out.println(); | ||
// 第三种状态切换 - 新建 -> 运行 -> 阻塞 -> 运行 -> 终止 | ||
threadRunTimeStatus3(); | ||
} | ||
|
||
public static void threadRunTimeStatus1() throws InterruptedException { | ||
System.out.println("#######第一种状态切换 -> 新建 -> 运行 -> 终止################################"); | ||
Thread thread1 = new Thread(new Runnable() { | ||
@Override | ||
public void run() { | ||
System.out.println("thread1当前状态:"+Thread.currentThread().getState().toString()); | ||
System.out.println("thread1执行了"); | ||
} | ||
}); | ||
System.out.println("没调用start方法,thread1当前状态:"+thread1.getState().toString()); | ||
thread1.start(); | ||
Thread.sleep(2000L); // 等待thread1执行完成后,再看线程状态 | ||
System.out.println("等待thread1执行完成后,再看线程状态:"+thread1.getState().toString()); | ||
// thread1.start(); TODO 注意,线程终止之后,再进行调用,会抛出IllegalThreadStateException异常 | ||
} | ||
|
||
public static void threadRunTimeStatus2() throws InterruptedException { | ||
System.out.println("############第二种:新建 -> 运行 -> 等待 -> 运行 -> 终止(sleep方式)###########################"); | ||
Thread thread2 = new Thread(new Runnable() { | ||
@Override | ||
public void run() { | ||
try { // 将线程thread2置位等待状态 1500毫秒后唤醒 | ||
Thread.sleep(1500L); | ||
}catch (InterruptedException e){ | ||
e.printStackTrace(); | ||
}finally { | ||
System.out.println("thread2当前状态:"+Thread.currentThread().getState().toString()); | ||
System.out.println("thread2执行了"); | ||
} | ||
} | ||
}); | ||
System.out.println("没调用start方法,thread2当前状态:"+thread2.getState().toString()); | ||
thread2.start(); | ||
Thread.sleep(200L); // 等待 200ms 再看thread2的状态 | ||
System.out.println("等待200毫秒,再看thread2当前状态:"+thread2.getState().toString()); | ||
Thread.sleep(3000L); // 等待 3000ms 再看thread2的状态 | ||
System.out.println("等待3秒,再看thread2当前状态:" + thread2.getState().toString()); | ||
} | ||
|
||
public static void threadRunTimeStatus3() throws InterruptedException { | ||
System.out.println("############第三种:新建 -> 运行 -> 阻塞 -> 运行 -> 终止###########################"); | ||
Thread thread3 = new Thread(new Runnable() { | ||
@Override | ||
public void run() { | ||
synchronized (Demo2.class) { | ||
System.out.println("thread3当前状态:" + Thread.currentThread().getState().toString()); | ||
System.out.println("thread3 执行了"); | ||
} | ||
} | ||
}); | ||
synchronized (Demo2.class){ | ||
System.out.println("没调用start方法,thread2当前状态:"+thread3.getState().toString()); | ||
thread3.start(); | ||
System.out.println("调用start方法,thread3当前状态:" + thread3.getState().toString()); | ||
Thread.sleep(200L); // 等待 200ms 再看thread3的状态 | ||
System.out.println("等待200ms,thread3当前状态:" + thread3.getState().toString()); | ||
} | ||
Thread.sleep(3000L); // 等待 3000ms 再看thread3的状态 | ||
System.out.println("等待3秒,让thread3抢到锁,再看thread3当前状态:" + thread3.getState().toString()); | ||
} | ||
|
||
|
||
} |
22 changes: 22 additions & 0 deletions
22
basejava/src/main/java/com/study/basejava/a1_thread_status/Demo3.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package com.study.basejava.a1_thread_status; | ||
|
||
/** | ||
* 示例3 - 线程stop强制性中止,破坏线程安全的示例 | ||
*/ | ||
public class Demo3 { | ||
public static void main(String[] args) throws InterruptedException { | ||
StopThread thread = new StopThread(); | ||
thread.start(); | ||
// 睡眠1s 确保变量自增成功 | ||
Thread.sleep(1000L); | ||
// 暂停线程 | ||
thread.stop(); // 错误的终止 | ||
// thread.interrupt(); | ||
while (thread.isAlive()){ | ||
System.out.println("线程的状态"+thread.getState().toString()); | ||
// 确保线程已经终止 | ||
} | ||
// 输出结果 | ||
thread.print(); | ||
} | ||
} |
25 changes: 25 additions & 0 deletions
25
basejava/src/main/java/com/study/basejava/a1_thread_status/Demo4.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
package com.study.basejava.a1_thread_status; | ||
|
||
/** | ||
* 通过状态位来判断 | ||
*/ | ||
public class Demo4 { | ||
public volatile static boolean flag = true; | ||
|
||
public static void main(String[] args) throws InterruptedException { | ||
new Thread(()->{ | ||
try { | ||
while (flag){ // 判断是否运行 | ||
System.out.println("运行中"+Thread.currentThread().getState().toString()); | ||
Thread.sleep(1000L); | ||
} | ||
}catch (InterruptedException e){ | ||
e.printStackTrace(); | ||
} | ||
}).start(); | ||
// 3秒之后,将状态标志改为False,代表不继续运行 | ||
Thread.sleep(3000L); | ||
flag = false; | ||
System.out.println("程序运行结束"+Thread.currentThread().getState().toString()); | ||
} | ||
} |
199 changes: 199 additions & 0 deletions
199
basejava/src/main/java/com/study/basejava/a1_thread_status/Demo5.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,199 @@ | ||
package com.study.basejava.a1_thread_status; | ||
|
||
import java.util.concurrent.locks.LockSupport; | ||
|
||
/** | ||
* 三种线程协作通信的方式:suspend/resume、wait/notify、park/unpark | ||
*/ | ||
public class Demo5 { | ||
// 包子店 | ||
public static Object baozidian = null ; | ||
|
||
/** | ||
* 正常的 suspend/resume | ||
*/ | ||
public void suspendResumeTest() throws InterruptedException { | ||
// 启动线程 | ||
Thread consumerThread = new Thread(()->{ | ||
if (baozidian == null){ // 如果没有包子,则进入等待状态 | ||
System.out.println("1. 进入等待状态"); | ||
Thread.currentThread().suspend(); | ||
} | ||
System.out.println("2. 买到包子,回家"); | ||
}); | ||
consumerThread.start(); | ||
// 等待3秒 生产一个包子 | ||
Thread.sleep(3000L); | ||
baozidian = new Object(); | ||
consumerThread.resume(); | ||
System.out.println("3. 通知消费者去消费"); | ||
} | ||
|
||
/** | ||
* 死锁的suspend/resume。 suspend并不会像wait一样释放锁,故此容易写出死锁代码 | ||
*/ | ||
public void suspendResumeDeadLockTest() throws InterruptedException { | ||
// 启动线程 | ||
Thread consumeThread = new Thread(() -> { | ||
if (baozidian == null) { | ||
System.out.println("1. 进入等待状态"); | ||
synchronized (this) { // 线程被挂起... 没人能够再次拿到锁 故进入死锁状态 | ||
Thread.currentThread().suspend(); | ||
} | ||
} | ||
System.out.println("2. 买到包子,回家"); | ||
}); | ||
consumeThread.start(); | ||
// 等待3秒 生产一个包子 | ||
Thread.sleep(3000L); | ||
baozidian = new Object(); | ||
// 争取到锁以后,再恢复consumerThread | ||
synchronized (this) { | ||
consumeThread.resume(); | ||
} | ||
System.out.println("3、通知消费者"); | ||
} | ||
/** | ||
* 导致程序永久挂起的suspend/resume | ||
*/ | ||
public void suspendResumeDeadLockTest2() throws InterruptedException { | ||
// 启动线程 | ||
Thread consumerThread = new Thread(() -> { | ||
if (baozidian == null) { | ||
System.out.println("1、没包子,进入等待"); | ||
try { // 为这个线程加上一点延时 | ||
Thread.sleep(5000L); | ||
} catch (InterruptedException e) { | ||
e.printStackTrace(); | ||
} | ||
// 这里的挂起执行在resume后面 | ||
Thread.currentThread().suspend(); | ||
} | ||
System.out.println("2、买到包子,回家"); | ||
}); | ||
consumerThread.start(); | ||
// 3秒之后,生产一个包子 | ||
Thread.sleep(3000L); | ||
baozidian = new Object(); | ||
consumerThread.resume(); | ||
System.out.println("3、通知消费者"); | ||
consumerThread.join(); | ||
} | ||
/** | ||
* 正常的wait、notify | ||
* @throws InterruptedException | ||
*/ | ||
public void waitNotifyTest() throws InterruptedException { | ||
new Thread(()->{ | ||
synchronized (this){ | ||
if (baozidian == null ){ | ||
System.out.println("1. 进入等待状态"); | ||
try { | ||
this.wait(); | ||
} catch (InterruptedException e) { | ||
e.printStackTrace(); | ||
} | ||
} | ||
} | ||
System.out.println("2. 买到包子,回家"); | ||
}).start(); | ||
// 3秒之后,生产一个包子 | ||
Thread.sleep(3000L); | ||
baozidian = new Object(); | ||
synchronized (this){ | ||
this.notify(); | ||
// this.notifyAll(); | ||
System.out.println("3、通知消费者"); | ||
} | ||
} | ||
|
||
/** | ||
* 会导致程序永久等待的wait/notify | ||
*/ | ||
public void waitNotifyDeadLockTest() throws InterruptedException { | ||
new Thread(()->{ | ||
if (baozidian == null ){ | ||
try { | ||
Thread.sleep(5000L); | ||
} catch (InterruptedException e) { | ||
e.printStackTrace(); | ||
} | ||
synchronized (this){ | ||
System.out.println("1、进入等待"); | ||
try { | ||
this.wait(); | ||
} catch (InterruptedException e) { | ||
e.printStackTrace(); | ||
} | ||
} | ||
} | ||
System.out.println("2、买到包子,回家"); | ||
}).start(); | ||
// 3秒之后,生产一个包子 | ||
Thread.sleep(3000L); | ||
baozidian = new Object(); | ||
synchronized (this){ | ||
this.notify(); | ||
// this.notifyAll(); | ||
System.out.println("3、通知消费者"); | ||
} | ||
} | ||
|
||
/** | ||
* 正常的park/unpark | ||
* @throws InterruptedException | ||
*/ | ||
public void parkUnparkTest() throws InterruptedException { | ||
Thread consumerThread = new Thread(()->{ | ||
while (baozidian == null){ | ||
System.out.println("1、进入等待"); | ||
LockSupport.park(); | ||
} | ||
System.out.println("2、买到包子,回家"); | ||
}); | ||
consumerThread.start(); | ||
Thread.sleep(3000L); | ||
baozidian = new Object(); | ||
LockSupport.unpark(consumerThread); | ||
System.out.println("3、通知消费者"); | ||
} | ||
|
||
/** | ||
* 死锁的park/unpark | ||
*/ | ||
public void parkUnparkDeadLockTest() throws InterruptedException { | ||
Thread consumerThread = new Thread(()->{ | ||
if (baozidian == null){ | ||
System.out.println("1、进入等待"); | ||
// 当前线程拿到锁,然后挂起 | ||
synchronized (this){ | ||
LockSupport.park(); | ||
} | ||
} | ||
}); | ||
consumerThread.start(); | ||
Thread.sleep(3000L); | ||
baozidian = new Object(); | ||
synchronized (this){ | ||
LockSupport.unpark(consumerThread); | ||
} | ||
System.out.println("3、通知消费者"); | ||
} | ||
|
||
public static void main(String[] args) throws InterruptedException { | ||
Demo5 demo5 = new Demo5(); | ||
// 对调用顺序有要求,也要开发自己注意锁的释放。这个被弃用的API, 容易死锁,也容易导致永久挂起。 | ||
// demo5.suspendResumeTest(); | ||
// demo5.suspendResumeDeadLockTest(); | ||
// demo5.suspendResumeDeadLockTest2(); | ||
|
||
// wait/notify要求再同步关键字里面使用,免去了死锁的困扰,但是一定要先调用wait,再调用notify,否则永久等待了 | ||
// demo5.waitNotifyTest(); | ||
// demo5.waitNotifyDeadLockTest(); | ||
|
||
// park/unpark没有顺序要求,但是park并不会释放锁,所有再同步代码中使用要注意 | ||
// demo5.parkUnparkTest(); | ||
demo5.parkUnparkDeadLockTest(); | ||
} | ||
|
||
} |
39 changes: 39 additions & 0 deletions
39
basejava/src/main/java/com/study/basejava/a1_thread_status/Demo6.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package com.study.basejava.a1_thread_status; | ||
|
||
/** | ||
* 线程封闭 | ||
*/ | ||
public class Demo6 { | ||
/** | ||
* threadLocal变量,每个线程都有一个副本,互不干扰 | ||
*/ | ||
public static ThreadLocal<String> value = new ThreadLocal<>(); | ||
|
||
/** | ||
* threadLocal测试 | ||
*/ | ||
public void threadLocalTest() throws InterruptedException { | ||
// threadlocal线程封闭示例 | ||
value.set("这是主线程设置的123"); | ||
String v = value.get(); | ||
System.out.println("线程1执行之前,主线程取到的值:" + v); | ||
new Thread(new Runnable() { | ||
@Override | ||
public void run() { | ||
String v = value.get(); | ||
System.out.println("线程1取到的值:" + v); | ||
value.set("这是线程1设置的456"); | ||
v = value.get(); | ||
System.out.println("重新设置之后,线程1取到的值:" + v); | ||
System.out.println("线程1执行结束"); | ||
} | ||
}).start(); | ||
Thread.sleep(5000L); | ||
v = value.get(); | ||
System.out.println("线程1执行之后,主线程取到的值:" + v); | ||
} | ||
|
||
public static void main(String[] args) throws InterruptedException { | ||
new Demo6().threadLocalTest(); | ||
} | ||
} |
Oops, something went wrong.