深入探究一下Java中不同的线程间数据通信方式

2023-07-04 0 2,296

目录

1、多线程如何共享数据

线程数据共享可以分为以下2种情况,线程实现代码相同及线程实现代码不同

线程实现代码相同

即runnable中的代码一致,这样可以直接在实现中定义成员变量直接共享

public class SharedSameRunnableDemo {
    public static void main(String[] args) {
        Runnable runnable = new MySameRunnable();
        Thread thread1 = new Thread(runnable);
        Thread thread2 = new Thread(runnable);
        thread1.start();
        thread2.start();
    }

    private static class MySameRunnable implements Runnable {
        private int sharedData = 0;

        @Override
        public synchronized void run() {
            for (int i = 0; i < 5; i++) {
                sharedData++;
                System.out.println(\"Thread: \" + Thread.currentThread().getName() + \",
                                   sharedData: \" + sharedData);
            }
        }
    }
}

在上面的示例中,我们定义了一个名为 MySameRunnable 的内部类它的共享变量是sharedData,它实现了Runnable 接口,并重写了 run() 方法。在 run() 方法中,我们使用了 synchronized 关键字来保证线程安全。然后在main() 方法中,我们创建了一个 MySameRunnable 实例 runnable,并将其传入两个不同的线程对象中。最后启动这两个线程。由于这两个线程共享同一个 MySameRunnable 实例,因此它们执行的代码是相同的,并且可以访问和修改sharedData 变量。通过这种方式,就可以实现多个线程共享数据,并确保线程安全。

线程实现代码不相同

即runnable中的代码不一致,MyRunnable1 MyRunnable2,利用一个对象SharedData,把runnable中的方法封装到这个对象中去,数据也在这个对象中。如果多个线程实现的代码不同,并且需要共享变量,可以使用一个单独的类来存储这些共享变量,并将它传递给所有的 Runnable 实例。以下是一个简单的示例代码:

public class SharedDifferentRauuableDemo {
    public static void main(String[] args) {
        SharedData sharedData = new SharedData();
        Thread thread1 = new Thread(new MyRunnable1(sharedData));
        Thread thread2 = new Thread(new MyRunnable2(sharedData));
        thread1.start();
        thread2.start();
    }

    private static class SharedData {
        private int data = 0;

        public synchronized void increment() {
            data++;
            System.out.println(\"IncrementThread: \" + data);
        }

        public synchronized void decrement() {
            data--;
            System.out.println(\"DecrementThread: \" + data);
        }
    }

    private static class MyRunnable1 implements Runnable {
        private SharedData sharedData;

        public MyRunnable1(SharedData sharedData) {
            this.sharedData = sharedData;
        }

        @Override
        public void run() {
            for (int i = 0; i < 5; i++) {
                sharedData.increment();
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private static class MyRunnable2 implements Runnable {
        private SharedData sharedData;
        public MyRunnable2(SharedData sharedData) {
            this.sharedData = sharedData;
        }
        @Override
        public void run() {
            for (int i = 0; i < 5; i++) {
                sharedData.decrement();
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

在上面的示例中,我们定义了一个 SharedData 类来存储共享变量 data。这个类包含两个同步方法 increment() 和 decrement(),用于增加和减少 data 的值,并输出当前的值。然后我们创建了两个 MyRunnable1 和 MyRunnable2 实例,它们分别传递了相同的 SharedData 对象。在 run() 方法中,它们调用 SharedData 对象的 increment() 和 decrement() 方法来进行数据修改,并使用 Thread.sleep() 方法让线程休眠一段时间。

通过这种方式,就可以实现多个线程共享数据,并确保线程安全。

2、子线程如何继承父线程数据

通过 InteritableThreadLocal实现共享

public class InheritableThreadLocalDemo {

    private static final InheritableThreadLocal<String> inheritableThreadLocal 
    = new InheritableThreadLocal<>();

    public static void main(String[] args) {
        inheritableThreadLocal.set(\"Hello, World!\");

        Thread parentThread = new Thread(() -> {
            System.out.println(\"Parent Thread: \" + inheritableThreadLocal.get());

            inheritableThreadLocal.set(\"Hello from Parent Thread!\");

            Thread childThread = new Thread(() -> {
                System.out.println(\"Child Thread: \" + inheritableThreadLocal.get());
            });

            childThread.start();
            try {
                childThread.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println(\"Parent Thread: \" + inheritableThreadLocal.get());
        });

        parentThread.start();
        try {
            parentThread.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println(\"Main Thread: \" + inheritableThreadLocal.get());

        inheritableThreadLocal.remove();
    }
}

在上面的示例中,我们创建了一个 InheritableThreadLocal 对象,并将其设置为“Hello, World!”。然后,我们创建了一个名为“parentThread”的线程,并在其中输出 inheritableThreadLocal 的值。接下来,我们在父线程中将 inheritableThreadLocal 的值设置为“Hello from Parent Thread!”,并创建了一个名为“childThread”的线程,在其中输出 inheritableThreadLocal 的值。

注意:由于 InheritableThreadLocal 是可继承的,所以在子线程中也能够获取到父线程中设置的值。因此,当我们在子线程中输出 inheritableThreadLocal 的值时,我们将看到输出“Hello from Parent Thread!”。

最后,我们分别在父线程、子线程和主线程中输出 inheritableThreadLocal 的值。由于我们在每个线程中都设置了 inheritableThreadLocal 的值,所以每个线程都将输出不同的值。

请注意,在程序的结尾处,我们调用了 inheritableThreadLocal.remove() 方法来清除 InheritableThreadLocal 对象的值,并释放相关的资源。这是一种良好的习惯,可以避免内存泄漏和数据污染等问题

3、相关问题

1.请简述Java中的多线程通信机制,并解释一下为什么需要多线程通信?

答:Java中的多线程通信机制是通过使用管道和共享变量来实现的。管道可以用来实现多个线程之间的数据传递和同步,共享变量可以用来实现多个线程之间的数据共享和同步。

2.Java 中,在多个线程之间共享数据的方式主要有以下几种:

1)共享变量:可以将需要共享的变量定义为静态变量或公共变量,然后通过同步控制机制(例如 synchronized 关键字、Lock 接口等)保证多线程访问这些变量时的安全性。

2)ThreadLocal:通过 ThreadLocal 类可以在每个线程中创建独立的变量副本,从而避免了对共享变量的竞争。

3)Callable 和 Future 接口:在子线程执行任务后,可以通过 Callable 和 Future 接口返回结果给主线程。主线程可以通过 Future.get() 方法获取子线程的执行结果,从而完成数据共享。

4)BlockingQueue:可以使用 BlockingQueue 来实现数据共享和通信,生产者线程向 BlockingQueue 中添加数据,消费者线程从队列中获取数据。

5)CyclicBarrier 和 CountDownLatch:可以使用 CyclicBarrier 和 CountDownLatch 等同步工具来协调多个线程之间的操作,从而实现数据共享。

资源下载此资源下载价格为1小猪币,终身VIP免费,请先
由于本站资源来源于互联网,以研究交流为目的,所有仅供大家参考、学习,不存在任何商业目的与商业用途,如资源存在BUG以及其他任何问题,请自行解决,本站不提供技术服务! 由于资源为虚拟可复制性,下载后不予退积分和退款,谢谢您的支持!如遇到失效或错误的下载链接请联系客服QQ:442469558

:本文采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可, 转载请附上原文出处链接。
1、本站提供的源码不保证资源的完整性以及安全性,不附带任何技术服务!
2、本站提供的模板、软件工具等其他资源,均不包含技术服务,请大家谅解!
3、本站提供的资源仅供下载者参考学习,请勿用于任何商业用途,请24小时内删除!
4、如需商用,请购买正版,由于未及时购买正版发生的侵权行为,与本站无关。
5、本站部分资源存放于百度网盘或其他网盘中,请提前注册好百度网盘账号,下载安装百度网盘客户端或其他网盘客户端进行下载;
6、本站部分资源文件是经压缩后的,请下载后安装解压软件,推荐使用WinRAR和7-Zip解压软件。
7、如果本站提供的资源侵犯到了您的权益,请邮件联系: 442469558@qq.com 进行处理!

猪小侠源码-最新源码下载平台 Java教程 深入探究一下Java中不同的线程间数据通信方式 http://www.20zxx.cn/774966/xuexijiaocheng/javajc.html

猪小侠源码,优质资源分享网

常见问题
  • 本站所有资源版权均属于原作者所有,均只能用于参考学习,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担
查看详情
  • 最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,建议提前注册好百度网盘账号,使用百度网盘客户端下载
查看详情

相关文章

官方客服团队

为您解决烦忧 - 24小时在线 专业服务