本文主要详细介绍Java线程间的通信,并结合代码和文本讨论线程间的通信。感兴趣的朋友可以参考一下。
本文总结了我对JAVA多线程中线程间通信的理解,主要通过代码和文本相结合的方式来讨论线程间的通信。因此,摘录了书中的一些示例代码,具体内容如下
同步
这里的同步意味着多个线程通过synchronized关键字相互通信。
参考示例:
公共类MyObject {
同步的公共void方法A() {
//做点什么.
}
同步的公共void方法B() {
//做一些其他的事情
}
}
公共类ThreadA扩展Thread {
私有MyObject对象;
//省略构造方法
@覆盖
公共无效运行(){
super . run();
object . methoda();
}
}
公共类ThreadB扩展Thread {
私有MyObject对象;
//省略构造方法
@覆盖
公共无效运行(){
super . run();
object . methodb();
}
}
公共类运行{
公共静态void main(String[] args) {
my object object=new my object();
//线程A和线程B持有相同的对象:object
ThreadA a=new ThreadA(object);
ThreadB b=new ThreadB(object);
a . start();
b . start();
}
}
因为线程A和线程B持有同一个MyObject类的object对象,虽然这两个线程需要调用不同的方法,但是它们是同步执行的。例如,线程B需要等待线程A执行完methodA()方法,然后才能执行methodB()方法。这样线程A和线程B就实现了通信。
这种方式,本质上就是“共享记忆”交流。多个线程需要访问同一个共享变量,谁得到锁(访问权)谁就可以执行。
while轮询的方式
代码如下:
导入Java . util . ArrayList;
导入Java . util . list;
公共类MyList {
private ListString list=new ArrayList string();
公共void add() {
list . add(“elements”);
}
public int size() {
返回list . size();
}
}
导入我的列表。MyList
公共类ThreadA扩展Thread {
私人MyList列表;
公共线程a(我的列表){
super();
this.list=list
}
@覆盖
公共无效运行(){
尝试{
for(int I=0;i 10i ) {
list . add();
system . out . println(' added '(I 1)' elements));
thread . sleep(1000);
}
} catch (InterruptedException e) {
e . printstacktrace();
}
}
}
导入我的列表。MyList
公共类ThreadB扩展Thread {
私人MyList列表;
公共线程b(我的列表){
super();
this.list=list
}
@覆盖
公共无效运行(){
尝试{
while (true) {
if (list.size()==5) {
System.out.println('==5,线程B准备退出');
抛出new interrupted exception();
}
}
} catch (InterruptedException e) {
e . printstacktrace();
}
}
}
导入我的列表。MyList
导入extthread。ThreadA
导入extthread。ThreadB
公共类测试{
公共静态void main(String[] args) {
my list service=new my list();
ThreadA a=new ThreadA(服务);
A . setname(“A”);
a . start();
ThreadB b=new ThreadB(服务);
B . set name(' B ');
b . start();
}
}
这样,线程A不断改变条件,线程ThreadB通过while语句不断检查这个条件(list.size()==5)是否为真,从而实现线程间的通信。但是这种方式会浪费CPU资源。之所以浪费资源,是因为JVM调度器把CPU交给线程B执行的时候,并没有做任何“有用”的工作,而是在不断测试某个条件是否成立。就像现实生活中,有人一直看着手机屏幕,看有没有来电,而不是:做别的。有电话时,按铃通知TA电话来了。关于线程轮询的影响,请参考:Java中一个线程执行无限循环的后果是什么?
wait/notify机制
代码如下:
导入Java . util . ArrayList;
导入Java . util . list;
公共类MyList {
private static ListString list=new ArrayList string();
公共静态void add() {
列表。add(“任何字符串”);
}
public static int size() {
返回列表。size();
}
}
公共类ThreadA扩展线程{
私有对象锁;
公共线程一个(对象锁){
super();
this.lock=lock
}
@覆盖
公共无效运行(){
尝试{
同步(锁定){
if (MyList.size()!=5) {
System.out.println('等待开始'
系统。当前时间毫秒());
锁定。wait();
System.out.println('等待结束'
系统。当前时间毫秒());
}
}
} catch (InterruptedException e) {
e。printstacktrace();
}
}
}
公共类ThreadB扩展线程{
私有对象锁;
公共线程乙(对象锁){
super();
this.lock=lock
}
@覆盖
公共无效运行(){
尝试{
同步(锁定){
for(int I=0;i 10i ) {
我的名单。add();
if (MyList.size()==5) {
锁定。notify();
System.out.println('已经发出了通知');
}
System.out.println('添加了我1 '个元素!');
线程。睡眠(1000);
}
}
} catch (InterruptedException e) {
e。printstacktrace();
}
}
}
公共类运行{
公共静态void main(String[] args) {
尝试{
对象锁=新对象();
ThreadA a=new ThreadA(lock);
答。start();
线程。睡眠(50);
ThreadB b=new ThreadB(lock);
乙。start();
} catch (InterruptedException e) {
e。printstacktrace();
}
}
}
线程A要等待某个条件满足时(list.size()==5),才执行操作。线程B则向目录中添加元素,改变目录的尺寸。
甲,乙之间如何通信的呢?也就是说,线程A如何知道list.size()已经为5了呢?
这里用到了目标类的等待()和通知()方法。
当条件未满足时(list.size()!=5),线程A调用等待()放弃CPU,并进入阻塞状态。 - 不像当轮询那样占用中央处理器
当条件满足时,线程B调用通知()通知线程一,所谓通知线程一,就是唤醒线程一,并让它进入可运行状态。
这种方式的一个好处就是中央处理器的利用率提高了。
但是也有一些缺点:比如,线程B先执行,一下子添加了5个元素并调用了通知()发送了通知,而此时线程A还执行;当线程A执行并调用等待()时,那它永远就不可能被唤醒了。因为,线程B已经发了通知了,以后不再发通知了。这说明:通知过早,会打乱程序的执行逻辑。
以上就是本文的全部内容,希望对大家学习Java 语言(一种计算机语言,尤用于创建网站)语言(一种计算机语言,尤用于创建网站)程序设计有所帮助。
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。