线程之间的通信
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线程之间的通信相关的知识,希望对你有一定的参考价值。
1.1、线程之间的通信方法
多个线程在处理统一资源,但是任务却不同,这时候就需要线程间通信。
等待/唤醒机制涉及的方法:
1. wait():让线程处于冻结状态,被wait的线程会被存储到线程池中。
2. notify():唤醒线程池中的一个线程(任何一个都有可能)。
3. notifyAll():唤醒线程池中的所有线程。
备注
1、这些方法都必须定义在同步中,因为这些方法是用于操作线程状态的方法。
2、必须要明确到底操作的是哪个锁上的线程!
3、wait和sleep区别?
1)wait可以指定时间也可以不指定。sleep必须指定时间。
2)在同步中时,对CPU的执行权和锁的处理不同。
wait:释放执行权,释放锁。
sleep:释放执行权,不释放锁。
为什么操作线程的方法wait、notify、notifyAll定义在了object类中,因为这些方法是监视器的方法,监视器其实就是锁。
锁可以是任意的对象,任意的对象调用的方式一定在object类中。
三、JDK 1.5新特性
一、Lock
Lock
实现提供了比使用 synchronized
方法和语句可获得的更广泛的锁定操作。此实现允许更灵活的结构,可以具有差别很大的属性,可以支持多个相关的 Condition
对象。
public interface Condition
Condition
将 Object
监视器方法(wait
、notify
和 notifyAll
)分解成截然不同的对象,以便通过将这些对象与任意 Lock
实现组合使用,为每个对象提供多个等待 set(wait-set)。其中,Lock
替代了 synchronized
方法和语句的使用,Condition
替代了 Object 监视器方法的使用。
线程常用方法
No.
|
方法名称
|
类型
|
描述
|
1
|
public Thread(Runnable target)
|
构造
|
接收Runnable接口子类对象,实例化Thread对象
|
2
|
public Thread(Runnable target,String name)
|
构造
|
接收Runnable接口子类对象,实例化Thread对象,并设置线程名称
|
3
|
public Thread(String name)
|
构造
|
实例化Thread对象,并设置线程名称
|
4
|
public static Thread currentThread()
|
普通
|
返回目前正在执行的线程
|
5
|
public final String getName()
|
普通
|
返回线程的名称
|
6
|
public final int getPriority()
|
普通
|
发挥线程的优先级
|
7
|
public boolean isInterrupted()
|
普通
|
判断目前线程是否被中断,如果是,返回true,否则返回false
|
8
|
public final boolean isAlive()
|
普通
|
判断线程是否在活动,如果是,返回true,否则返回false
|
9
|
public final void join() throws InterruptedException
|
普通
|
等待线程死亡
|
10
|
public final synchronized void join(long millis) throws InterruptedException
|
普通
|
等待millis毫秒后,线程死亡
|
11
|
public void run()
|
普通
|
执行线程
|
12
|
public final void setName(String name)
|
普通
|
设定线程名称
|
13
|
public final void setPriority(int newPriority)
|
普通
|
设定线程的优先值
|
14
|
public static void sleep(long millis) throws InterruptedException
|
普通
|
使目前正在执行的线程休眠millis毫秒
|
15
|
public void start()
|
普通
|
开始执行线程
|
16
|
public static void yield()
|
普通
|
将目前正在执行的线程暂停,允许其它线程执行
|
17
|
public final void setDaemon(boolean on)
|
普通
|
将一个线程设置成后台运行
|
18
|
public final void setPriority(int newPriority)
|
普通
|
更改线程的优先级
|
五、守护线程和线程优先级
5.1、守护线程-后台资源
setDaemon
public final void setDaemon(boolean on)将该线程标记为守护线程或用户线程。
当正在运行的线程都是守护线程时,Java 虚拟机退出。
该方法必须在启动线程前调用。
该方法首先调用该线程的 checkAccess 方法,且不带任何参数。这可能抛出 SecurityException(在当前线程中)。
参数:
on - 如果为 true,则将该线程标记为守护线程。
抛出:
IllegalThreadStateException - 如果该线程处于活动状态。
SecurityException - 如果当前线程无法修改该线程。
当前台线程都结束时,后台线程自动结束。
5.2、线程优先级
setPriority
public final void setPriority(int newPriority)更改线程的优先级。
首先调用线程的 checkAccess 方法,且不带任何参数。这可能抛出 SecurityException。
在其他情况下,线程优先级被设定为指定的 newPriority 和该线程的线程组的最大允许优先级相比较小的一个。
参数:
newPriority - 要为线程设定的优先级
抛出:
IllegalArgumentException - 如果优先级不在 MIN_PRIORITY 到 MAX_PRIORITY 范围内。
10-----1------------5
static int |
MAX_PRIORITY 线程可以具有的最高优先级。 |
static int |
MIN_PRIORITY 线程可以具有的最低优先级。 |
static int |
NORM_PRIORITY 分配给线程的默认优先级。 |
SecurityException - 如果当前线程无法修改该线程。
getPriority
public final int getPriority()返回线程的优先级。
返回:
该线程的优先级。
六、join线程
作用:阻塞指定的线程等到另一个线程完成以后,再继续执行
package com.pb.thread.demo2; public class MyThread implements Runnable { @Override public void run() { for(int x=0;x<10;x++){ System.out.println(Thread.currentThread().getName()+"....."+x); } } } //============= package com.pb.thread.demo2; public class Demo { public static void main(String[] args) { MyThread my=new MyThread(); Thread t1=new Thread(my); t1.setName("半路加入的线程"); for(int x=0;x<10;x++){ if(x==5){ try { t1.start(); t1.join(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(Thread.currentThread().getName()+"....."+x); } } }
结果:
main.....0 main.....1 main.....2 main.....3 main.....4 半路加入的线程.....0 半路加入的线程.....1 半路加入的线程.....2 半路加入的线程.....3 半路加入的线程.....4 半路加入的线程.....5 半路加入的线程.....6 半路加入的线程.....7 半路加入的线程.....8 半路加入的线程.....9 main.....5 main.....6 main.....7 main.....8 main.....9
或者
package com.pb.thread.demo2; public class Test { public static void main(String[] args) { for(int x=0;x<10;x++){ if(x==5){ try { Thread t1=new Thread(new MyThread(),"半路加入的线程"); t1.start(); t1.join(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(Thread.currentThread().getName()+"....."+x); } } }
七、yield
yield
public static void yield()暂停当前正在执行的线程对象,并执行其他线程。
package com.pb.thread.demo2; public class MyThread implements Runnable { @Override public void run() { for(int x=0;x<10;x++){ System.out.println(Thread.currentThread().getName()+"....."+x); Thread.yield(); } } } //=========== package com.pb.thread.demo2; public class Test { public static void main(String[] args) { new Thread(new MyThread(),"线程一").start(); new Thread(new MyThread(),"线程二").start(); } }
八、停止线程
开启多线程,运行代码通常是循环结构
只要控制住循环,就可以让run方法结束。也就是线程结束。
package com.pb.thread.demo4; public class StopThread implements Runnable { private boolean flag=true; @Override public void run() { while(flag){ System.out.println(Thread.currentThread().getName()+"......run"); } } public void setChangeFlag(){ this.flag=false; } public static void main(String[] args) { StopThread st=new StopThread(); Thread t1=new Thread(st); Thread t2=new Thread(st); t1.start(); t2.start(); int num=0; while(true){ if(num++==60){ st.setChangeFlag(); break; } System.out.println(Thread.currentThread().getName()+"===="+num); } } }
interrupt
public void interrupt()
如果线程在调用 Object
类的 wait()
、wait(long)
或 wait(long, int)
方法,或者该类的join()
、join(long)
、join(long, int)
、sleep(long)
或 sleep(long, int)
方法过程中受阻,则其中断状态将被清除,它还将收到一个 InterruptedException
。
package com.pb.thread.demo4; public class StopThread implements Runnable { private boolean flag = true; @Override public synchronized void run() { while (flag) { try { wait(); } catch (InterruptedException e) { // e.printStackTrace(); System.out.println(Thread.currentThread().getName() + "......Exception"); flag = false; //设置标识为false } System.out.println(Thread.currentThread().getName() + "......run"); } } public void setChangeFlag() { this.flag = false; } public static void main(String[] args) { StopThread st = new StopThread(); Thread t1 = new Thread(st); Thread t2 = new Thread(st); t1.start(); t2.start(); int num = 0; while (true) { if (num++ == 60) { //中断状态也就是冻结状态,回到运行状态 t1.interrupt(); t2.interrupt(); break; } System.out.println(Thread.currentThread().getName() + "====" + num); } System.out.println("over"); } }
main====1 main====2 main====3 main====4 main====5 main====6 main====7 main====8 main====9 main====10 main====11 main====12 main====13 main====14 main====15 main====16 main====17 main====18 main====19 main====20 main====21 main====22 main====23 main====24 main====25 main====26 main====27 main====28 main====29 main====30 main====31 main====32 main====33 main====34 main====35 main====36 main====37 main====38 main====39 main====40 main====41 main====42 main====43 main====44 main====45 main====46 main====47 main====48 main====49 main====50 main====51 main====52 main====53 main====54 main====55 main====56 main====57 main====58 main====59 main====60 over Thread-1......Exception Thread-1......run Thread-0......Exception Thread-0......run
九、sleep();
sleep
public static void sleep(long millis) throws InterruptedException
在指定的毫秒数内让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度程序精度和准确性的影响。该线程不丢失任何监视器的所属权。
-
参数:
millis
- 以毫秒为单位的休眠时间。抛出:
InterruptedException
- 如果任何线程中断了当前线程。当抛出该异常时,当前线程的中断状态 被清除。
十、toString
toString
public String toString()
返回该线程的字符串表示形式,包括线程名称、优先级和线程组。
- 返回:
- 该线程的字符串表示形式。
package com.pb.thread.demo4; public class StopThread implements Runnable { private boolean flag = true; @Override public synchronized void run() { while (flag) { System.out.println(Thread.currentThread().toString()+ "......run"); } } public void setChangeFlag() { this.flag = false; } public static void main(String[] args) { StopThread st = new StopThread(); Thread t1 = new Thread(st); Thread t2 = new Thread(st); t1.start(); t2.start(); int num = 0; while (true) { if (num++ == 60) { st.setChangeFlag(); break; } System.out.println(Thread.currentThread().toString()+ "====" + num); } System.out.println("over"); } }
Thread[Thread-0,5,main]......run Thread[main,5,main]====1 Thread[Thread-0,5,main]......run Thread[main,5,main]====2 Thread[Thread-0,5,main]......run Thread[main,5,main]====3 Thread[Thread-0,5,main]......run Thread[main,5,main]====4 Thread[main,5,main]====5 Thread[main,5,main]====6 Thread[main,5,main]====7 Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[main,5,main]====8 Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[main,5,main]====9 Thread[Thread-0,5,main]......run Thread[main,5,main]====10 Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[main,5,main]====11 Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[main,5,main]====12 Thread[main,5,main]====13 Thread[main,5,main]====14 Thread[main,5,main]====15 Thread[main,5,main]====16 Thread[Thread-0,5,main]......run Thread[main,5,main]====17 Thread[main,5,main]====18 Thread[main,5,main]====19 Thread[main,5,main]====20 Thread[main,5,main]====21 Thread[main,5,main]====22 Thread[main,5,main]====23 Thread[main,5,main]====24 Thread[main,5,main]====25 Thread[main,5,main]====26 Thread[main,5,main]====27 Thread[main,5,main]====28 Thread[main,5,main]====29 Thread[main,5,main]====30 Thread[main,5,main]====31 Thread[main,5,main]====32 Thread[main,5,main]====33 Thread[main,5,main]====34 Thread[main,5,main]====35 Thread[main,5,main]====36 Thread[main,5,main]====37 Thread[main,5,main]====38 Thread[main,5,main]====39 Thread[main,5,main]====40 Thread[main,5,main]====41 Thread[main,5,main]====42 Thread[main,5,main]====43 Thread[main,5,main]====44 Thread[main,5,main]====45 Thread[main,5,main]====46 Thread[main,5,main]====47 Thread[main,5,main]====48 Thread[main,5,main]====49 Thread[main,5,main]====50 Thread[main,5,main]====51 Thread[main,5,main]====52 Thread[main,5,main]====53 Thread[main,5,main]====54 Thread[main,5,main]====55 Thread[main,5,main]====56 Thread[main,5,main]====57 Thread[main,5,main]====58 Thread[main,5,main]====59 Thread[main,5,main]====60 over Thread[Thread-0,5,main]......run
Thread[Thread-0,5,main]......run Thread[main,5,main]====1 Thread[Thread-0,5,main]......run Thread[main,5,main]====2 Thread[Thread-0,5,main]......run Thread[main,5,main]====3 Thread[Thread-0,5,main]......run Thread[main,5,main]====4 Thread[main,5,main]====5 Thread[main,5,main]====6 Thread[main,5,main]====7 Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[main,5,main]====8 Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[main,5,main]====9 Thread[Thread-0,5,main]......run Thread[main,5,main]====10 Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[main,5,main]====11 Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[Thread-0,5,main]......run Thread[main,5,main]====12 Thread[main,5,main]====13 Thread[main,5,main]====14 Thread[main,5,main]====15 Thread[main,5,main]====16 Thread[Thread-0,5,main]......run Thread[main,5,main]====17 Thread[main,5,main]====18 Thread[main,5,main]====19 Thread[main,5,main]====20 Thread[main,5,main]====21 Thread[main,5,main]====22 Thread[main,5,main]====23 Thread[main,5,main]====24 Thread[main,5,main]====25 Thread[main,5,main]====26 Thread[main,5,main]====27 Thread[main,5,main]====28 Thread[main,5,main]====29 Thread[main,5,main]====30 Thread[main,5,main]====31 Thread[main,5,main]====32 Thread[main,5,main]====33 Thread[main,5,main]====34 Thread[main,5,main]====35 Thread[main,5,main]====36 Thread[main,5,main]====37 Thread[main,5,main]====38 Thread[main,5,main]====39 Thread[main,5,main]====40 Thread[main,5,main]====41 Thread[main,5,main]====42 Thread[main,5,main]====43 Thread[main,5,main]====44 Thread[main,5,main]====45 Thread[main,5,main]====46 Thread[main,5,main]====47 Thread[main,5,main]====48 Thread[main,5,main]====49 Thread[main,5,main]====50 Thread[main,5,main]====51 Thread[main,5,main]====52 Thread[main,5,main]====53 Thread[main,5,main]====54 Thread[main,5,main]====55 Thread[main,5,main]====56 Thread[main,5,main]====57 Thread[main,5,main]====58 Thread[main,5,main]====59 Thread[main,5,main]====60 over Thread[Thread-0,5,main]......run
十一、匿名内部类实现多线程
package com.pb.thread.demo4; /* * 匿名内部类实现多线程 */ public class ThreadTest { public static void main(String[] args) { //线程对象 new Thread(){ public void run(){ for (int x = 0; x < 100; x++) { System.out.println(Thread.currentThread().getName()+".........."+x); } } }.start(); //Runnable 接口 Runnable r=new Runnable(){ public void run(){ for (int x = 0; x < 100; x++) { System.out.println(Thread.currentThread().getName()+".........."+x); } } }; //启动线程 new Thread(r).start(); } }
以上是关于线程之间的通信的主要内容,如果未能解决你的问题,请参考以下文章
是否最好使用 Activity.onAttachFragment 或 Fragment.onAttach 在 Activity 和嵌套片段之间进行通信?