java new thread参数_Java带参数的线程类ParameterizedThread——即如何给Thread传递参数...

在Java中似乎没有提供带运行参数的线程实现类,在第三方类库中也没有找到。网上有大量的文章在讨论这个问题,但都没有提供很好的代码封装解决方案,这令我很吃惊。如果读者知道有官方或者第三方的实现方式,欢迎留言说明。本文最后给出了一种实现带运行参数的线程实现类。

在C#的基础类库中早就提供了相关的解决方案,如下是C#几种常见的带参数子线程创建方法:

Thread th = new Thread((param) =>{

Console.WriteLine(param);

});

th.Start(i);

Task.Factory.StartNew((param) =>{

Console.WriteLine(param);

}, i);

ThreadPool.QueueUserWorkItem((param) =>{

Console.WriteLine(param);

}, i);

让我们从一个实际编码问题开始讲起,主线程循环一个集合元素,并创建子线程中做相应的处理(可能比较耗时)。下面是最初的一段实现代码,请问这段代码存在什么问题?

for (int i = 0; i < 100; i++) {

Thread th = new Thread(newRunnable() {

@Override

public voidrun() {

System.out.println(i + "");}

});

th.start();

}

(1)首先这段程序是无法通过编译的,在intellij idea中提示“Variable 'i' is accessed from within inner class,needs to be final or effectively final”,在Eclipse中提示"Local variable i defined in an enclosing scope must be final or effectively final",意思是说在内部类中无法访问外部类中不是final修饰的成员变量。那么我们很容易想通过下面的方式解决:

for (int i = 0; i < 100; i++) {

int p =i;

Thread th = new Thread(newRunnable() {

@Override

public voidrun() {

System.out.println(p + "");

}

});

th.start();

}

这段代码能够通过编译,而且似乎运行良好。但是不是线程安全的,父线程中的循环变量不断被修改,子线程得到的父线程成员变量可能是不正确的。

(2)其次上面的代码在循环体内创建了大量的子线程,线程的创建和销毁会造成系统资源的开销,一般推荐使用线程池的方式创建线程,比如ThreadPoolExecutor。

ThreadPoolExecutor executor = new ThreadPoolExecutor(6, 10, 5, TimeUnit.SECONDS, new LinkedBlockingQueue());

for (int i = 0; i < 100; i++) {

int p=i;

executor.execute(()->{

System.out.println(p + "");

});

}

那么有什么办法使得子线程能够安全的获取到父线程的变量呢,我们可以编写如下的线程实现类:

public class MyRunnable implementsRunnable {

Object param;

publicMyRunnable(Object parameter) {

this.param =parameter;

}

@Override

public voidrun() {

System.out.println(param.toString());

}

}

这里的问题是我们必须针对不同的情形,编写不同的子线程实现类,在各个工程中分散了很多类似的脚手架代码,闻到这种“味道”,我们应该想到需要进行代码抽象和封装,以便于重复使用。据此,笔者用Java封装了一个带参数的线程类:

/*** ParameterizedThreadStart defines the start method for starting a thread.

* @authorwadexmy

* @param

*/

public interface ParameterizedThreadStart{

/*** a method with parameter

* @paramcontext

*/

voidrun(T context);

}

/**

* ParameterizedThread defines a thread with a generic parameter

* @author wadexmy

* @param

*/

public class ParameterizedThreadimplements Runnable{

privateT context;

private ParameterizedThreadStartparameterStart;

/**

* Constructor

* @param context

*/

public ParameterizedThread(T context,ParameterizedThreadStartparameterStart){

this.context=context;

this.parameterStart=parameterStart;

}

/**

* getContext returns the context of current thread.

* @return

*/

publicT getContext(){

returncontext;

}

/**

* run method to be called in that separately executing thread.

*/@Override

public voidrun() {

parameterStart.run(context);

}

}

类ParameterizedThread实现了 Runnable,在构造方法中传递了一个参数和需要执行的方法。可以通过下面的代码测试这个类:

ThreadPoolExecutor executor = new ThreadPoolExecutor(6, 10, 5, TimeUnit.SECONDS, new LinkedBlockingQueue());

for (int i = 0; i < 100; i++) {

executor.execute(new ParameterizedThread<>(i, (p) ->{

System.out.println(p.toString());

}));

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值