精华内容
下载资源
问答
  • Java 多线程通信

    千次阅读 2018-10-14 10:52:47
    然而,并不是启动越多线程,就能让程序执行越快,多线程同时带来了上下文切换、多线程间的通信与同步、死锁等问题。合理的利用多线程进行编程是一件有挑战性的事。 Java自一开始就内置了对多线程的支持,在JDK1.5...

    并发编程,一般指多线程编程,它可以充分利用计算机的计算资源,使得一个任务可以分为几个子模块同时执行,提高程序执行速度。然而,并不是启动越多线程,就能让程序执行越快,多线程同时带来了上下文切换、多线程间的通信与同步、死锁等问题。合理的利用多线程进行编程是一件有挑战性的事。

    Java 自一开始就内置了对多线程的支持,在 JDK1.5 版本中引入了 java.util.concurrent 包,让 Java 的并发编程有了更多的选择和更好的工作方式。


    多线程带来的问题

    看下面一个例子,猜一下它的输出结果:

    public class MultiThread {
        static int i = 0;
        public static int get() {
            return i++;
        }
    
        public static void main(String[] args) {
            for (int t = 0; t < 10; t++) {
                new Thread() {
                    public void run() {
                        System.out.println(get());
                    }
                }.start();
            }
        }
    }
    

    输出结果:

    1
    0
    2
    3
    4
    5
    6
    7
    8
    9
    

    注意,输出结果是不确定的,虽然大部分输出情况都是0-9顺序输出,但总会出现“异常情况”,也就是发生了冲突,当线程越多冲突的机会就越大。

    输出结果不确定的原因在于程序中开了10个线程,而这10个线程是同步执行的,可能第二个线程比第一个线程先进行输出,也就出现了上面的结果。至于为什么大部分情况都是按顺序输出,因为虽然这10个线程是同步执行的,但是它们的启动顺序不一样,第一个线程最先启动,最后一个线程最后启动。


    让线程按顺序输出

    如果现在有10个线程,编号为0-9,我们想让0号线程执行完再执行1号线程,以此类推,最后执行9号线程。解决的方法是使用线程的 join() 方法。

    假设线程的名字叫做 t,t.join() 方法的作用是将当前线程加入 t 线程,当 t 线程执行完后再执行当前线程。

    示例如下:

    public class JoinDemo {
        public static void main(String[] args) {
            Thread[] threads = new Thread[10];
            for (int i = 0; i < 10; i++) {
                threads[i] = new Thread(String.valueOf(i)) {
                    public void run() {
                        String name = Thread.currentThread().getName();
                        int number = Integer.parseInt(name);
                        if (number > 0)
                            try {
                                threads[number - 1].join();
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        System.out.println("线程名:" + name);
                    }
                };
                threads[i].start();
            }
        }
    }
    

    输出结果:

    线程名:0
    线程名:1
    线程名:2
    线程名:3
    线程名:4
    线程名:5
    线程名:6
    线程名:7
    线程名:8
    线程名:9
    

    程序中我们让后一个线程加到前一个线程中,使得只有前一个线程执行完了才能执行后一个线程。

    t.join() 方法内部实际上是调用了 Object的wait() 方法,因此使用 join() 方法之前,需要先获得当前对象的锁,执行 wait() 方法后会释放当前对象的锁。


    等待通知机制

    等待/通知机制,是指一个线程A调用了对象 O 的 wait() 方法进入等待状态,另一个线程B调用了对象 O 的 notify() 或 notifyAll() 方法通知在对象上等待的线程,使其从 wait() 状态返回。两个线程间通过对象 O 来交互。

    notify() 与 notifyAll() 的区别在于前者只会通知一个在对象上等待的线程,如果在该对象上等待的线程有多个,则会随机选取一个;后者会通知所有等待在该对象中的线程。

    注意,对于 notifyAll() 来说,虽然所有的线程都被通知了。但是这些线程会进行竞争,且只会有一个线程成功获取到锁,在这个线程执行完毕之前,其他的线程必须等待。但 notifyAll() 免去了线程运行完后再通知其他线程的必要,因为之前已经通知过了所有的线程。

    示例如下:

    public class WaitNotify {
        static Object lock = new Object();
    
        static class Wait implements Runnable {
            public void run() {
                synchronized (lock) {
                    System.out.println("线程" + Thread.currentThread().getName() + "开始等待");
                    try {
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("继续执行时间:" + LocalTime.now().withNano(0));
                }
            }
        }
    
        static class Notify implements Runnable {
            public void run() {
                synchronized (lock) {
                    System.out.println("线程" + Thread.currentThread().getName() + "开始通知");
                    lock.notify();
                    System.out.println("通知时间:" + LocalTime.now().withNano(0));
                }
            }
        }
    
        public static void main(String[] args) {
            Thread wait = new Thread(new Wait(), "wait");
            Thread notify = new Thread(new Notify(), "notify");
            wait.start();
            notify.start();
        }
    }
    

    输出结果:

    线程wait开始等待
    线程notify开始通知
    通知时间:12:20:45
    继续执行时间:12:20:45
    

    注意,执行 notify() 或 notifyAll() 方法时不会释放 lock 的锁,直到 notify 线程释放了 lock 后,wait 线程才能从 wait() 方法中返回。

    展开全文
  • 主要介绍了Java多线程通信实现方式详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
  • 主要介绍了Java多线程通信:交替打印ABAB实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
  • java多线程通信图解

    2017-11-29 20:03:50
    一张图方便理解和掌握java 多线程之间通信的实质 java 多线程 其实就是每个线程都拥有自己的内存空间,多线程之间的通信,比例A线程修改了主内存(main方法的线程)变量,需要把A线程修改的结果同步到主线程中,...
  • 主要介绍了Java多线程通信wait()和notify()代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
  •  多线程通信,其实是多个线程操操作同一个资源,但是操作方式不同。典型实例有生产者和消费者,本文也通过实例来分析线程等待唤醒机制。  1、相关API介绍  public final void notify()  唤醒在此对象监视...
  • 一个多线程通信服务端程序的简单例子,可以根据情况增加业务逻辑。
  • Java多线程通信:交替打印ABAB

    千次阅读 2018-08-20 16:35:38
    使用wait()和notify()实现Java多线程通信:两个线程交替打印A和B,如ABABAB public class Test { public static void main(String[] args) { final PrintAB print = new PrintAB(); new Thread(new Runnable() ...

    使用wait()和notify()实现Java多线程通信:两个线程交替打印A和B,如ABABAB

    public class Test {
       public static void main(String[] args) {
           final PrintAB print = new PrintAB();
    
           new Thread(new Runnable() {
               public void run(){
                   for(int i=0;i<5;i++) {
                       print.printA();
                       }
                       }
           }).start();
    
           new Thread(new Runnable() {
               public void run() {
                   for(int i=0;i<5;i++) {
                       print.printB(); }
                                }
             }).start();
           }
     }
    
     class PrintAB{
        private boolean flag = true;
    
        public synchronized void printA () {
                while(!flag) {
                    try {
                        this.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                                 } }
                    System.out.print("A");
                     flag = false;
                     this.notify();
                }
    
        public synchronized void printB () {
                while(flag) {
                    try {
                        this.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.print("B");
                flag = true;
                this.notify(); }
     }
    展开全文
  • java多线程通信基础(面向厕所编程)

    千次阅读 2021-01-31 11:47:15
    公厕(公厕的坑位是共享资源)中无论多少人(人是线程)排队,只要你锁好厕门(synchronized)就不会出现线程安全问题,无论排队的多么着急都要一个个来,锁门期间(同步代码块内/同步方法内)调用sleep相当于你蹲坑期间睡着...

    大纲:java线程知识体系

    一、sleep与wait的区别,先举例,再理论!
    公厕(公厕的坑位是共享资源)中无论多少人(人是线程)排队,只要你锁好厕门(synchronized)就不会出现线程安全问题,无论排队的多么着急都要一个个来,锁门期间(同步代码块内/同步方法内)调用sleep相当于你蹲坑期间睡着了,那么门锁(同步锁)肯定不会自动打开,依然是锁着的,除非时间到了你睡醒了然后该干嘛干嘛,否则只能通过粗暴的方式先把你叫醒(interreput方法)再说。wait相当于你礼让他人,先主动打开门锁(wait调用后会释放同步锁)让出坑位给别人,然后主动去加入排队蹲坑的大部队中边睡觉(进程陷入阻塞态)边等待。

    二 、notify和notifyAll()
    如果有人上完厕所,出来后看到睡眠中的排队者们,可以通过只叫醒一个(notify,使进程由阻塞态 => 就绪态),但叫醒的一定是憋的最着急的人(优先级最高的线程),被叫醒的人能立刻获得坑位资源。另外,也可以选择一次性唤醒所有(notifyAll)排队者,这时排队者会一窝蜂涌入争夺坑位,可无论多么激烈,只能有一个人抢占坑位,优先级越高的线程抢到茅坑资源的概率越大

    sleep和wait都是用来进行线程控制,都可以使线程阻塞
    1 sleep(milliseconds)可以用时间指定来使他自动醒过来,如果时间不到你只能调用interreput()来强行打断;wait()可以用notify()/notifyAll()直接唤起.
    2. sleep是Thread类的静态方法。 sleep的作用是让线程休眠制定的时间,在时间到达时恢复,也就是说sleep将在接到时间到达事件事恢复线程 ; wait是Object的方法,也就是说可以对任意一个对象调用wait方法,调用wait方法将会将调用者的线程挂起,直到其他线程调用同一个对象的notify方法才会重新激活调用者
    3. sleep()是让某个线程暂停运行一段时间,其控制范围是由当前线程决定,wait()是由某个确定的对象来调用的。

    sleep和wait的区别有:
    1、这两个方法来自不同的类分别是Thread和Object
    2、最主要是sleep方法没有释放锁,而wait方法释放了锁,使得其他线程可以使用同步控制块或者方法。
    3、wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用
    4、sleep必须捕获异常,而wait,notify和notifyAll不需要捕获异常

    经典案例,交替打印0~9

    public class Accounter implements Runnable{
    
        private int index;
        @Override
        public void run() {
            String name = Thread.currentThread().getName();
            synchronized (this){
                while (index < 10){
                    notify();
                    System.out.println(name + "打印:" + index);
                    index++;
                    try {
                        wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    
        public static void main(String[] args) {
            Accounter accounter = new Accounter();
            Thread thread = new Thread(accounter);
            Thread thread2 = new Thread(accounter);
            thread.start();
            thread2.start();
        }
    }
    

    推荐学习:消费者生产者案例

    展开全文
  • 请大家尊重劳动成果,转载请注明出处:...  Java多线程之间要交换信息,有时只能用管道来完成,在使用管道通信时,经常会碰到“java - IOException: Read end dead”或者“java - IOException: Write end dead”的异

        请大家尊重劳动成果,转载请注明出处:http://blog.csdn.net/caoshichao520326/article/details/8995583

        Java多线程之间要交换信息,有时只能用管道来完成,在使用管道通信时,经常会碰到“java - IOException: Read end dead”或者“java - IOException: Write end dead”的异常,下面针对这个问题作出一个简单的分析,首先是写了一个管道通信的demo供大家参考。程序如下:

    package com.csc.pipetest;
    
    import java.io.IOException;
    import java.io.PipedInputStream;
    import java.io.PipedOutputStream;
    
    /**
     * 管道通信demo
     * 
     * @author csc
     * 
     */
    public class PipeTest {
    
    	public static void main(String[] args) {
    
    		// 创建管道输出流
    		PipedOutputStream pos = new PipedOutputStream();
    		// 创建管道输入流
    		PipedInputStream pis = new PipedInputStream();
    		try {
    			// 将管道输入流与输出流连接 此过程也可通过重载的构造函数来实现
    			pos.connect(pis);
    		} catch (IOException e) {
    			e.printStackTrace();
    		}
    		// 创建生产者线程
    		Producer p = new PipeTest().new Producer(pos);
    		// 创建消费者线程
    		Consumer c = new Consumer(pis);
    		// 启动线程
    		p.start();
    		c.start();
    	}
    
    	// 生产者线程(与一个管道输入流相关联)
    	private class Producer extends Thread {
    		private PipedOutputStream pos;
    
    		public Producer(PipedOutputStream pos) {
    			this.pos = pos;
    		}
    
    		public void run() {
    			int i = 8;
    			// while (true) {//加入此句将出现“java - IOException: Read end dead”异常
    			try {
    				pos.write(i);
    			} catch (IOException e) {
    				e.printStackTrace();
    			}
    			// }
    
    		}
    	}
    
    	// 消费者线程(与一个管道输入流相关联)
    	private static class Consumer extends Thread {
    		private PipedInputStream pis;
    
    		public Consumer(PipedInputStream pis) {
    			this.pis = pis;
    		}
    
    		public void run() {
    			// while(true){//加入此句将出现“java - IOException: Write end dead”异常
    			try {
    				System.out.println(pis.read());
    			} catch (IOException e) {
    				e.printStackTrace();
    			}
    			// }
    
    		}
    	}
    }
    

        上面的程序是可以正确运行的,①若将第46行和第52行注释掉的代码加上,将会抛出“java - IOException: Read end dead”。②若将第66行和第72行注释掉的代码加上,将会抛出“java - IOException: Write end dead”。原因都是一样的:在利用管道读写数据时,必须保证利用管道读写数据的线程都不能退出。针对上面的程序,如果是第①种情况,是因为Consumer(消费者)线程在读出管道中的数据后,线程就运行结束退出了。这时再向建立链接管道的线程Producer中写入数据时就会抛出异常。同样,如果是第②种情况就,是因为Producer(生产者)线程在写入管道中的数据后,线程就运行结束退出了。这时再由建立链接管道的线程Consumer中读出数据时就会抛出异常。

        细心的读者会发现,程序的第37行和第58行在创建内部类是一个使用了“static”关键字,一个没有使用,这决定了程序的第28行和第30行在使实例化对象时的方式不同,这是创建内部类要求的否则会出现编译错误,详细分析见:http://blog.csdn.net/caoshichao520326/article/details/8961297

    展开全文
  • JAVA 多线程通信 详解与举例

    万次阅读 2013-05-27 16:11:02
    为了实现线程通信,我们可以使用Object类提供的wait()、notify()、notifyAll()三个方法。调用wait()方法会释放对该同步监视器的锁定。这三个方法必须由同步监视器对象来调用,这可分成两种情况: 对于使用...
  • Java多线程通信机制

    千次阅读 2012-12-26 16:54:34
    Java提供了3个非常重要的方法来巧妙地解决线程间的通信问题。这3个方法分别是:wait()、notify()和notifyAll()。它们都是Object类的最终方法,因此每一个类都默认拥有它们。  虽然所有的类都默认拥有这3个方法,...
  • package demo; public class Demo3 { public static void main(String[] args) { final Print_ print = new Print_(); new Thread(new Runnable() { public void run() { for(int i=0 ;
  • 该练习题需要借助Java传统的线程通信的知识。 首先,我们创建了一个打印类Print,该类中分别实现了打印数字printNums()方法、以及打印字符printChars()方法。 class Print { private boolean flag=false; ...
  • 本文主要介绍java 多线程-线程通信 这里整理了相关资料及示例代码,有兴趣的小伙伴可以参考下
  • 主要介绍了Java Socket实现多线程通信功能,结合具体实例形式较为详细的分析了java多线程通信的原理及客户端、服务器端相应实现技巧,需要的朋友可以参考下
  • 万字图解Java多线程

    万次阅读 多人点赞 2020-09-06 14:45:07
    java多线程我个人觉得是javaSe中最难的一部分,我以前也是感觉学会了,但是真正有多线程的需求却不知道怎么下手,实际上还是对多线程这块知识了解不深刻,不知道多线程api的应用场景,不知道多线程的运行流程等等,...
  • 主要介绍了Java多线程中线程间的通信实例详解的相关资料,需要的朋友可以参考下
  • 主要介绍了Java多线程线程通信生产者消费者模式及等待唤醒机制代码详解,具有一定参考价值,需要的朋友可以了解下。
  • 主要为大家详细介绍了java多线程编程之线程间的通信,探讨使用管道进行通信,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • Java 多线程通信及线程安全

    千次阅读 2018-05-16 16:57:27
     java中使用多线程操作同一数据时,需要考虑到线程间的通讯,否则会出现数据错误,程序死锁卡死的情况。所以多线程在操作同一数据时必须考虑其先后顺序以保证数据准确,且不会出现死锁的情况。多线程间的通信往往是...
  • 基于多线程实现的JavaSocket客户端-服务端点对点异步通信程序代码
  • Java多线程

    万次阅读 多人点赞 2021-06-11 16:28:49
    Java多线程Java多线程线程的创建线程常见方法线程的状态线程的优先级守护线程线程组Java线程池线程池的创建线程池的参数线程池的使用线程不安全问题Java中的锁synchronized同步方法synchronized同步语句块...
  • 下面小编就为大家带来一篇java多线程编程学习(线程间通信)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • Java多线程实现TCP网络Socket编程(C/S通信)

    万次阅读 多人点赞 2020-10-26 09:45:38
    本篇详细记录实现java多线程通信,目标达到客户端可以一次接收服务器发送的多条信息,避免阻塞。将客户端接收信息功能独立为一个线程来完成,进一步完善TCP的Socket网络通信,C/S软件架构的程序设计!
  • 下面小编就为大家带来一篇深入理解JAVA多线程之线程间的通信方式。小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • Java多线程协同通信,学习总结

    万次阅读 2020-01-26 11:22:15
    多线程编程时,往往需要线程间协同通信,比如控制运行顺序、等待处理结果等。Java提供的多种控制方式可以满足不同场景需求。 学习资料:https://mp.weixin.qq.com/s/NUJL_mEfXSo0e-nf2UUNJQ 示例代码:...
  • Java多线程基础(四)Java传统线程同步通信技术编写代码实现以下功能子线程循环10次,接着主线程循环100次,接着又回到子线程循环10次,接着再回到主线程又循环100次,如此循环50次。分析1)子线程循环10次与主线程...
  • Java线程通信详解

    2020-09-01 08:37:44
    本篇文章主要介绍了Java线程通信问题,线程通信用来保证线程协调运行,有需要的朋友可以了解一下。

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 233,126
精华内容 93,250
关键字:

java多线程通信

java 订阅