龙空技术网

Java多线程编程:探究不同的线程间数据通信方式

玄明Hanko 133

前言:

现时看官们对“java多线程传参”都比较重视,兄弟们都需要知道一些“java多线程传参”的相关知识。那么小编同时在网摘上网罗了一些对于“java多线程传参””的相关资讯,希望姐妹们能喜欢,小伙伴们一起来学习一下吧!

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、相关问题请简述Java中的多线程通信机制,并解释一下为什么需要多线程通信?

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

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

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

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

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

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

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

标签: #java多线程传参 #java与数据库之间的通信