Thread 中方法
注意为什么 sleep(),currentThread(),interrupted(),yield()这些方法是静态方法, 因为设计一个线程的 run()方法的时候, 需要改变当前线程的状态, 而当前线程对象未定义完毕无法调用函数, 在这种情况下可以直接调动静态方法 (等同于当前线程直接调用了该方法), 或者调用 currentThread() 方法来获取当前线程对象.
如:
- public static void main(String[] args) {
- Thread t = new Thread(() ->{
- try {
- Thread.sleep(1000);
- int result = A/B;
- // 错误: The local variable t may not have been initialized
- t.join();
- System.out.println(result);
- } catch (InterruptedException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- });
- 1,setDaemon
setDaemon(boolean on): 将该线程标记为守护线程或用户线程.
当前线程结束, 守护线程也跟着结束
必须在调用 start()方法前, 调用 setDaemon 方法
2, 优先级
getId(): 返回该线程的标识符.
getPriority(): 返回线程的优先级.
setPriority(int newPriority): 更改线程的优先级.
3,join
join(): 当前线程等待调用该方法线程结束, 也就是让 "主线程" 等待 "子线程" 结束之后才能继续运行.
join(time): 当前线程等到调用该方法多长时间
Thread.currentThread().join(): 当前线程等待当前线程的结束, 程序处于一直运行的状态
是封装了 wait 方法
join 相比 wait 而言, join 是只能让当前线程等待, 而 wait 可以让任意调用这个函数的线程等待.
根据底层实现原理, 只要调用这个函数的 "子线程" 一直没死亡, 那么会一直调用这个函数, 使得当前线程一直等待, 直到 "子线程" 结束没法在调用 join 函数为止
更多资料:
join 和 Daemon 对比
join 是等待一个线程结束后在执行当前线程, Daemon 是守护线程和当前线程并发进行.
4, 中断线程 interrupt interrputed
可以中断 wait(),sleep(), 或者 join()方法
中断并不是指直接中断 run 方法, 只是中断 wait(),sleep(),join()方法返回一个异常, run 还能正常执行
interrupt()是实例方法
interrupted()是类方法, 测试当前线程是否已经中断, 底层调用的还是 isInterrupted()
对比: interrupt() interrupted()
- public class CreateThread {
- public static void main(String[] args) throws InterruptedException {
- Thread t = new Thread() {
- public void run() {
- while (true) {
- try {
- Thread.sleep(1000000);
- } catch (InterruptedException e) {
- System.out.println("收到打断信号.");
- // 调用的是实例方法
- System.out.println(isInterrupted()); //false
- }
- }
- }
- };
- t.start();
- Thread.sleep(1000);
- System.out.println(t.isInterrupted()); //false
- t.interrupt(); // 中断了 sleep()方法, 但是 run()方法并未中断
- System.out.println(t.isInterrupted()); //true
- }
- }
- public class CreateThread {
- private static final Object MONITOR = new Object();
- public static void main(String[] args) throws InterruptedException {
- Thread t = new Thread(() ->{
- while(true) {
- synchronized(MONITOR) {
- try {
- MONITOR.wait(10);
- } catch (InterruptedException e) {
- // 调用的是 currentThread().isInterrupted(true)
- // interrupted 是静态方法
- System.out.println(">>"+Thread.interrupted());
- }
- }
- }
- });
- t.start();
- Thread.sleep(1000);
- System.out.println(t.isInterrupted());
- t.interrupt();
- System.out.println(t.isInterrupted());
- }
- }
总结:
当 Thread 是直接重写 run 方法的时候, 可以直接调用 isInterrupted 方法, 相当于 this.isInterrupted().
当 Thread 中传入的是 Runnable 的时候, 在 Runnable 中的 run 方法中不能调用实例方法, 因为 run 方法是封装在 RUnnable 接口里面, 在这种情况下, 只能调用类的方法.
中断 join 方法
调用 join 的是当前线程, 不是实例线程
代码示例:
- public class CreateThread {
- public static void main(String[] args) throws InterruptedException {
- Thread t = new Thread() {
- public void run() {
- while(true) {
- }
- }
- };
- t.start();
- Thread main = Thread.currentThread();
- Thread t2 = new Thread() {
- public void run() {
- try {
- Thread.sleep(100);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- // 真正要打断的是 main 线程, 才能打断 join 方法
- main.interrupt();
- System.out.println("Interrupt");
- }
- };
- t2.start();
- try {
- // 真正调用 join()方法的是当前的线程 main, 并不是 t 线程
- t.join();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- 5, yield
参考链接: https://blog.csdn.net/dabing69221/article/details/17426953
使当前线程从执行状态 (运行状态) 变为可执行态(就绪状态).
让出 CPU 的执行权
之后所有线程 (包括让出的这一线程) 同时竞争 CPU 的执行权.
打个比方: 现在有很多人在排队上厕所, 好不容易轮到这个人上厕所了, 突然这个人说:"我要和大家来个竞赛, 看谁先抢到厕所!", 然后所有的人在同一起跑线冲向厕所, 有可能是别人抢到了, 也有可能他自己有抢到了. 我们还知道线程有个优先级的问题, 那么手里有优先权的这些人就一定能抢到厕所的位置吗? 不一定的, 他们只是概率上大些, 也有可能没特权的抢到了.
- public class YieldTest extends Thread {
- public YieldTest(String name) {
- super(name);
- }
- @Override
- public void run() {
- for (int i = 1; i <= 50; i++) {
- System.out.println(""+ this.getName() +"-----" + i);
- // 当 i 为 30 时, 该线程就会把 CPU 时间让掉, 让其他或者自己的线程执行(也就是谁先抢到谁执行)
- if (i == 30) {
- this.yield();
- }
- }
- }
- public static void main(String[] args) {
- YieldTest yt1 = new YieldTest("张三");
- YieldTest yt2 = new YieldTest("李四");
- yt1.start();
- yt2.start();
- }
- }
注意: 这个不存在线程安全的问题, 因为 i 是局部变量(是每个线程自己所私有的), 不存在数据共享的问题.
单个线程也不存在线程安全的问题, 代码是按照顺序执行(当然在底层会改变一些数据, 但是代码执行的逻辑并未发生改变), 所以单个线程会依次打印出 1--50
运行结果:
李四 -----1
张三 -----1
李四 -----2
张三 -----2
李四 -----3
张三 -----3
李四 -----4
张三 -----4
李四 -----5
张三 -----5
李四 -----6
张三 -----6
李四 -----7
张三 -----7
李四 -----8
张三 -----8
李四 -----9
张三 -----9
张三 -----10
张三 -----11
张三 -----12
张三 -----13
张三 -----14
张三 -----15
张三 -----16
张三 -----17
张三 -----18
张三 -----19
张三 -----20
张三 -----21
张三 -----22
张三 -----23
张三 -----24
张三 -----25
张三 -----26
张三 -----27
张三 -----28
张三 -----29
张三 -----30
李四 -----10
李四 -----11
李四 -----12
李四 -----13
李四 -----14
李四 -----15
李四 -----16
李四 -----17
李四 -----18
李四 -----19
李四 -----20
李四 -----21
李四 -----22
李四 -----23
李四 -----24
李四 -----25
李四 -----26
李四 -----27
李四 -----28
李四 -----29
李四 -----30
张三 -----31
张三 -----32
张三 -----33
张三 -----34
张三 -----35
张三 -----36
张三 -----37
张三 -----38
张三 -----39
张三 -----40
张三 -----41
张三 -----42
张三 -----43
张三 -----44
张三 -----45
张三 -----46
张三 -----47
张三 -----48
张三 -----49
张三 -----50
李四 -----31
李四 -----32
李四 -----33
李四 -----34
李四 -----35
李四 -----36
李四 -----37
李四 -----38
李四 -----39
李四 -----40
李四 -----41
李四 -----42
李四 -----43
李四 -----44
李四 -----45
李四 -----46
李四 -----47
李四 -----48
李四 -----49
李四 -----50
来源: http://www.bubuko.com/infodetail-3424446.html