您的位置:首页 > 编程语言 > Java开发

java多线程-Thread两个线程交换数据Exchanger

2017-04-25 10:27 776 查看
背景 继续讲解关于多线程的两个或双数个的数据交换,使用Exchanger类进行。那么除此之外再讲解下如何给线程里面传值,并且如何从一个已经结束的线程里面取值,传出来使用。把线程的一些常用的东西记录下。
详细说明 先来一个demo,对两个进程进行数据交换。Exchanger,这个类的名字也十分直接,不就是交换器吗。
/**
* 2017-4-21
* author:饶为
* Administrator
*/
package Thread;
import java.util.concurrent.Exchanger;

/**
* 2017-4-21
* author:饶为
* Administrator
*/
public class ExchangerTest {
public static void main(String[] args) {
final Exchanger<String> exchanger = new Exchanger<String>();

new Thread(){
public void run(){
String a = "第一个线程";
try {
a = exchanger.exchange(a);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Thread1"+a);
}
}.start();

new Thread(){
public void run(){
String a = "第二个线程";
try {
a = exchanger.exchange(a);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Thread2"+a);
}
}.start();
}
}
很直观,直接把两个线程数据调换过来了。可以根据运行结果,来进行查看。那么这个类是可以运行在双数进程上,如果再添加一个进程,则第三个进程不运行。
那么我们可以实验下双数的运行结果,我添加四个进程。
/**
* 2017-4-21
* author:饶为
* Administrator
*/
package Thread;
import java.util.concurrent.Exchanger;

/**
* 2017-4-21
* author:饶为
* Administrator
*/
public class ExchangerTest {
public static void main(String[] args) {
final Exchanger<String> exchanger = new Exchanger<String>();

new Thread(){
public void run(){
String a = "第一个线程";
try {
a = exchanger.exchange(a);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Thread1"+a);
}
}.start();

new Thread(){
public void run(){
String a = "第二个线程";
try {
a = exchanger.exchange(a);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Thread2"+a);
}
}.start();

new Thread(){
public void run(){
String a = "第三个线程";
try {
a = exchanger.exchange(a);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Thread3"+a);
}
}.start();

new Thread(){
public void run(){
String a = "第四个线程";
try {
a = exchanger.exchange(a);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Thread4"+a);
}
}.start();
}
}
运行结果如下

 很明显吧,1和2的数据交换了,3和4的交换了。那么大家可以自己尝试下单数个线程使用。
一个进程执行完后,把数据传值到另一个进程中
这个其实很简单,就是需要传出去的进程设置一个方法,得到想要的数据,当这个进程执行完后,去执行另一个进程。这里我提供两个方法,一个是Join(),一个是CountDownLatch类。
一、使用join方法来实现执行完线程后,再去执行其他方法。代码如下首先先弄一个传数据出去的类,称为传出类。那传出类代码很简单,我贴下
/**
* 2017-4-21
* author:饶为
* Administrator
*/
package Thread;
/**
* 2017-4-21
* author:饶为
* Administrator
*/
public class Exchanger1 extends Thread {

String aString;

/* (non-Javadoc)
* @see java.lang.Thread#run()
*/
@Override
public void run() {
// TODO Auto-generated method stub
this.aString="我的线程1";

try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

public String getS(){
return aString;
}
}
这里注意的就是getS这个方法,这个是用来传值的。接下来是接收这个线程传值的方法。
ublic class ET {
public static void main(String[] args) throws InterruptedException {
exchanger.start();
countDownLatch.await();
Exchanger1 exchanger = new Exchanger1();
exchanger.start();
exchanger.join();

String a = exchanger.getS();
System.out.println(a);

}
}
讲讲这个join方法,这个其实是就是只有线程执行完后,才会运行下面的方法,它其实join()方法的实现原理是不停检查join线程是否存活,如果join线程存活则让当前线程永远等待。直到join线程完成后,线程的this.notifyAll()方法会被调用。那么运行结果,就是ET类,接收到了传出类的数据。
二、使用CountDownLatch
public class Exchanger1 extends Thread {

private CountDownLatch countDownLatch;
public Exchanger1(CountDownLatch countDownLatch){
this.countDownLatch = countDownLatch;
}
String aString;

/* (non-Javadoc)
* @see java.lang.Thread#run()
*/
@Override
public void run() {
// TODO Auto-generated method stub
this.aString="我的线程1";

try {
Thread.sleep(5000);
countDownLatch.countDown();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

publ
a264
ic String getS(){
return aString;
}
}

这个是传出类。CountDownLatch,我之前的博文中已经介绍了它的使用方法,就是当cdl减少为0的时候,才会继续执行下面的代码,否则会阻塞。那么接收类代码为
public class ET {
public static void main(String[] args) throws InterruptedException {
CountDownLatch countDownLatch = new CountDownLatch(1);
Exchanger1 exchanger = new Exchanger1(countDownLatch);

exchanger.start();
countDownLatch.await();
String a = exchanger.getS();
System.out.println(a);
}
}
很明显,用await方法阻塞,当执行了countdown方法后,countdownlatch为0,则继续执行下面代码。活学活用之前学习的东西

。其实使用cyclibarier也是可以做到这个效果的,还记的吗?只要把接收类也变为线程类就可以了。然后在new的时候,添加执行类。就Ok了。可以参考之前博文
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: