在传统的同步开发模式下当我们调用一个函数时通过这个函数的参数将数据传入并通过这个函数的返回值来返回最终的计算结果但在多线程的异步开发模式下数据的传递和返回和同步开发模式有很大的区别由于线程的运行和结束是不可预料的因此在传递和返回数据时就无法象函数一样通过函数参数和return语句来返回数据本文就以上原因介绍了几种用于向线程传递数据的方法在下一篇文章中将介绍从线程中返回数据的方法
欲先取之必先予之一般在使用线程时都需要有一些初始化数据然后线程利用这些数据进行加工处理并返回结果在这个过程中最先要做的就是向线程中传递数据
一通过构造方法传递数据
在创建线程时必须要建立一个Thread类的或其子类的实例因此我们不难想到在调用start方法之前通过线程类的构造方法将数据传入线程并将传入的数据使用类变量保存起来以便线程使用(其实就是在run方法中使用)下面的代码演示了如何通过构造方法来传递数据
package mythread;
public class MyThread extends Thread
{
private String name;
public MyThread(String name)
{
thisname = name;
}
public void run()
{
Systemoutprintln(hello + name);
}
public static void main(String[] args)
{
Thread thread = new MyThread(world);
threadstart();
}
}
由于这种方法是在创建线程对象的同时传递数据的因此在线程运行之前这些数据就就已经到位了这样就不会造成数据在线程运行后才传入的现象如果要传递更复杂的数据可以使用集合类等数据结构使用构造方法来传递数据虽然比较安全但如果要传递的数据比较多时就会造成很多不便由于Java没有默认参数要想实现类似默认参数的效果就得使用重载这样不但使构造方法本身过于复杂又会使构造方法在数量上大增因此要想避免这种情况就得通过类方法或类变量来传递数据
二通过变量和方法传递数据
向对象中传入数据一般有两次机会第一次机会是在建立对象时通过构造方法将数据传入另外一次机会就是在类中定义一系列的public的方法或变量(也可称之为字段)然后在建立完对象后通过对象实例逐个赋值下面的代码是对MyThread类的改版使用了一个setName方法来设置name变量
package mythread;
public class MyThread implements Runnable
{
private String name;
public void setName(String name)
{
thisname = name;
}
public void run()
{
Systemoutprintln(hello + name);
}
public static void main(String[] args)
{
MyThread myThread = new MyThread();
myThreadsetName(world);
Thread thread = new Thread(myThread);
threadstart();
}
}
三通过回调函数传递数据
上面讨论的两种向线程中传递数据的方法是最常用的但这两种方法都是main方法中主动将数据传入线程类的这对于线程来说是被动接收这些数据的然而在有些应用中需要在线程运行的过程中动态地获取数据如在下面代码的run方法中产生了个随机数然后通过Work类的process方法求这三个随机数的和并通过Data类的value将结果返回从这个例子可以看出在返回value之前必须要得到三个随机数也就是说这个value是无法事先就传入线程类的
package mythread;
class Data
{
public int value = ;
}
class Work
{
public void process(Data data Integer numbers)
{
for (int n : numbers)
{
datavalue += n;
}
}
}
public class MyThread extends Thread
{
private Work work;
public MyThread(Work work)
{
thiswork = work;
}
public void run()
{
javautilRandom random = new javautilRandom();
Data data = new Data();
int n = randomnextInt();
int n = randomnextInt();
int n = randomnextInt();
workprocess(data n n n); // 使用回调函数
Systemoutprintln(StringvalueOf(n) + + + StringvalueOf(n) + +
+ StringvalueOf(n) + = + datavalue);
}
public static void main(String[] args)
{
Thread thread = new MyThread(new Work());
threadstart();
}
}
在上面代码中的process方法被称为回调函数从本质上说回调函数就是事件函数在Windows API中常使用回调函数和调用API的程序之间进行数据交互因此调用回调函数的过程就是最原始的引发事件的过程在这个例子中调用了process方法来获得数据也就相当于在run方法中引发了一个事件