【Java多线程】如何给线程传递数据及让线程返回数据
⼀.如何给线程传递数据
1.通过构造⽅法传递数据
在创建线程时,必须要创建⼀个Thread类的或其⼦类的实例。因此可以在调⽤start⽅法之前,通过 线程类的构造⽅法 将数据传⼊线程。并将传⼊的数据使⽤ 成员变量接收 ,以便线程体使⽤
/**
* TODO 测试线程传递参数1-通过构造⽅法传递数据
*/
public class TestThreadPassParam1 extends Thread {
//⽤于接受构造⽅法传进来的数据
private String name;
//构造⽅法
public TestThreadPassParam1(String name){
this.name = name;
}
//线程体
@Override
public void run(){
System.out.println("hello "+ name);
}
public static void main(String[] args){
Thread thread =new TestThreadPassParam1("world");
thread.start();
}
}
通过构造⽅法传递数据的,在线程运⾏之前这些数据就就已经到位了,这样就不会造成数据在线程运⾏后才传⼊的现象。如果要传递更复杂的数据,可通过类⽅法或类变量来传递数据。
2.通过变量和⽅法传递数据
向对象中传⼊数据⼀般有两次机会,第⼀次机会是在建⽴对象时通过构造⽅法将数据传⼊,另外⼀次机会就是在类中定义⼀系列的public的⽅法或变量(也可称之为字段)。然后在建⽴完对象后,通过对象实例逐个赋值。下⾯的代码是对MyThread1类的改版,使⽤了⼀个setName⽅法来设置name变量:
/**
* @Description TODO 测试线程传递参数2-通过变量和⽅法传递数据
*/
public class TestThreadPassParam2 extends Thread {
/
/传递参数
private String food;
public void setFood(String food){
this.food = food;
}
//线程体
@Override
public void run(){
System.out.println("吃"+ food);
}
public static void main(String[] args){
TestThreadPassParam2 myThread =new TestThreadPassParam2();
myThread.setFood("包⼦");
Thread thread =new Thread(myThread);
thread.start();
}
}
3.通过回调函数传递数据
上⾯两种向线程传递数据的⽅法是最常⽤的。都是在主线程main()中主动将数据传⼊线程类的。这对于线程来说,是被动接收这些数据的。然⽽,在有些应⽤中需要在线程运⾏的过程中动态地获取数据.
如: 在下⾯代码的run⽅法中产⽣了3个随机数,然后通过Work类的process⽅法求这三个随机数的和,并通过Data类的value将结果返回。从这个例⼦可以看出,在返回value之前,必须要得到三个随机数。也就是说,这个value是⽆法事先就传⼊线程类的。
import java.util.Random;
/**
* @Description TODO 测试线程传递参数3-通过回调函数传递数据
*/
public class TestThreadPassParam3 extends Thread {
//传递参数
private Work work;
//构造⽅法
public TestThreadPassParam3(Work work){
this.work = work;
}
/
/线程体
public void run(){
//声明Data对象
Data data =new Data();
//声明随机对象
Random random =new Random();
int n1 = Int(1000);//随机数1
int n2 = Int(2000);//随机数2
int n3 = Int(3000);//随机数3
//线程内调⽤work对象的.process⽅法
work.process(data, n1, n2, n3);// 使⽤回调函数
System.out.println(n1 +"+"+ n2 +"+"+ n3 +"="+ data.value);
}
public static void main(String[] args){
Thread thread =new TestThreadPassParam3(new Work());
thread.start();
}
}
//计数器
class Data {
public int value =0;
}
/
/在线程内回调,⽤于将numbers的值累加到Data.value
class Work {
public void process(Data data, numbers){
for(Integer n : numbers){
data.value += n;
}
}
}
在上⾯代码中的process⽅法被称为回调函数。从本质上说,回调函数就是事件函数。调⽤回调函数的过程就是最原始的触发事件的过程。在这个例⼦中调⽤了process⽅法来获得数据也就相当于在run⽅法中引发了⼀个事件。
⼆.如何让线程返回数据
从线程中返回数据和向线程传递数据类似,也可以通过类成员以及回调函数来返回数据,但类成员在返回数据和传递数据时有⼀些区别1.主线程等待
使⽤这种⽅法返回数据需要在线程完成后才能通过类变量或⽅法得到数据
/**
* TODO 测试线程返回数据1-通过主线程等待返回数据
*/
public class TestThreadReturnData1 extends Thread {
private Count count;
TestThreadReturnData1(Count count){
}
@Override
public void run(){
for(int i =0;i<10;i++){
}
}
public static void main(String[] args)throws InterruptedException {
Count count =new Count();
Thread thread =new Thread(new TestThreadReturnData1(count));
thread.start();
// 获取⼦线程的返回值:主线程等待法
Value()==0){
Thread.sleep(1000);
}
System.out.Value());
System.out.println("主线程执⾏完毕");
}
}
//计数器
@Data
class Count {
public int value =0;
}
2.Join⽅法阻塞当前线程以等待⼦线程执⾏完毕
使⽤join⽅法可以让⼦线程执⾏完毕后再执⾏主线程,本质和通过循环判断⼀样
import lombok.Data;
/**
* @Description TODO 测试线程返回数据1-通过Join⽅法阻塞当前线程以等待⼦线程执⾏完毕返回数据
*/
public class TestThreadReturnData2 extends Thread {
private Count2 count;
TestThreadReturnData2(Count2 count){
}
@Override
public void run(){
for(int i =0;i<10;i++){
}
}
public static void main(String[] args)throws InterruptedException {
Count2 count =new Count2();
Thread thread =new Thread(new TestThreadReturnData2(count));
thread.start();
// 获取⼦线程的返回值:Thread的join⽅法来阻塞主线程,直到⼦线程返回
thread.join();
nextint()方法System.out.Value());
System.out.println("主线程执⾏完毕");
}
}
//计数器
@Data
class Count2 {
public int value =0;
}
3.使⽤Callable接⼝和FutureTask
在JDK1.5加⼊了Callable接⼝,实现该接⼝并重写call()⽅法也能创建新线程,并且该⽅法是有返回值的!
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论