副标题#e#
在传统的同步开拓模式下,当我们挪用一个函数时,通过这个函数的参数将数据传入,并通过这个函数的返回值来返回最终的计较功效。但在多线程的异步开拓模式下,数据的通报和返回和同步开拓模式有很大的区别。由于线程的运行和竣事是不行预料的,因此,在通报和返回数据时就无法象函数一样通过函数参数和return语句来返回数据。本文就以上原因先容了几种用于向线程通报数据的要领,在下一篇文章中将先容从线程中返回数据的要领。
欲先取之,必先予之。一般在利用线程时都需要有一些初始化数据,然后线程操作这些数据举办加工处理惩罚,并返回功效。在这个进程中最先要做的就是向线程中通报数据。
一、通过结构要领通报数据
在建设线程时,必需要成立一个Thread类的或其子类的实例。因此,我们不难想到在挪用start要领之前通过线程类的结构要领将数据传入线程。并将传入的数据利用类变量生存起来,以便线程利用(其实就是在run要领中利用)。下面的代码演示了如何通过结构要领来通报数据:
package mythread;
public class MyThread1 extends Thread
{
private String name;
public MyThread1(String name)
{
this.name = name;
}
public void run()
{
System.out.println("hello " + name);
}
public static void main(String[] args)
{
Thread thread = new MyThread1("world");
thread.start();
}
}
由于这种要领是在建设线程工具的同时通报数据的,因此,在线程运行之前这些数据就就已经到位了,这样就不会造成数据在线程运行后才传入的现象。假如要通报更巨大的数据,可以利用荟萃、类等数据布局。利用结构要领来通报数据固然较量安详,但假如要通报的数据较量多时,就会造成许多未便。由于Java没有默认参数,要想实现雷同默认参数的结果,就得利用重载,这样不单使结构要领自己过于巨大,又会使结构要领在数量上大增。因此,要想制止这种环境,就得通过类要领或类变量来通报数据。
二、通过变量和要领通报数据
向工具中传入数据一般有两次时机,第一次时机是在成立工具时通过结构要领将数据传入,别的一次时机就是在类中界说一系列的public的要领或变量(也可称之为字段)。然后在成立落成具后,通过工具实例逐个赋值。下面的代码是对MyThread1类的改版,利用了一个setName要领来配置name变量:
package mythread;
public class MyThread2 implements Runnable
{
private String name;
public void setName(String name)
{
this.name = name;
}
public void run()
{
System.out.println("hello " + name);
}
public static void main(String[] args)
{
MyThread2 myThread = new MyThread2();
myThread.setName("world");
Thread thread = new Thread(myThread);
thread.start();
}
}
#p#副标题#e#
三、通过回调函数通报数据
上面接头的两种向线程中通报数据的要领是最常用的。但这两种要领都是main要领中主动将数据传入线程类的。这对付线程来说,是被动吸收这些数据的。然而,在有些应用中需要在线程运行的进程中动态地获取数据,如在下面代码的run要领中发生了3个随机数,然后通过Work类的process要领求这三个随机数的和,并通过Data类的value将功效返回。从这个例子可以看出,在返回value之前,必需要获得三个随机数。也就是说,这个value是无法事先就传入线程类的。
package mythread;
class Data
{
public int value = 0;
}
class Work
{
public void process(Data data, Integer numbers)
{
for (int n : numbers)
{
data.value += n;
}
}
}
public class MyThread3 extends Thread
{
private Work work;
public MyThread3(Work work)
{
this.work = work;
}
public void run()
{
java.util.Random random = new java.util.Random();
Data data = new Data();
int n1 = random.nextInt(1000);
int n2 = random.nextInt(2000);
int n3 = random.nextInt(3000);
work.process(data, n1, n2, n3); // 利用回调函数
System.out.println(String.valueOf(n1) + "+" + String.valueOf(n2) + "+"
+ String.valueOf(n3) + "=" + data.value);
}
public static void main(String[] args)
{
Thread thread = new MyThread3(new Work());
thread.start();
}
}
#p#分页标题#e#
在上面代码中的process要领被称为回调函数。从本质上说,回调函数就是事件函数。在Windows API中常利用回调函数和挪用API的措施之间举办数据交互。因此,挪用回调函数的进程就是最原始的激发事件的进程。在这个例子中挪用了process要领来得到数据也就相当于在run要领中激发了一个事件。