java多线程run方法传参

多线程参数传递技巧
本文介绍了在Java中实现多线程时如何向线程传递参数的三种常见方法:通过构造方法、通过变量或方法、以及通过回调函数。具体展示了如何在Runnable接口的实现类中使用这些方法。

      我们知道多线程是通过star()方法让线程处于准备就绪状态,而实际运行的业务逻辑是放在run()方法体中的,但是run()方法是没有参数的方法,实际的业务场景中,我们可能需要向方法体中传递参数,下面介绍常用的两种传参方式,第三种下次再说,或者你们百度吧,这里偷个懒。

      第一种方式:构造方法传参

public class CallbackCustomerTypeThread implements Runnable
{
	public static final Logger logger = LoggerFactory.getLogger(CallbackCustomerTypeThread.class);
	private BasCmCustomerType basCmCustomerType;
	private BasCmCustomerTypeService basCmCustomerTypeService;

	public CallbackCustomerTypeThread(BasCmCustomerType basCmCustomerType, BasCmCustomerTypeService basCmCustomerTypeService)
	{
		this.basCmCustomerType = basCmCustomerType;
		this.basCmCustomerTypeService = basCmCustomerTypeService;
	}

	@Override
	public void run()
	{
		//向金剑南同步
		try
		{
			basCmCustomerTypeService.syncToJjn(basCmCustomerType);
		}
		catch (Exception e)
		{
			logger.info("向金剑南同步客户异常,id=" + basCmCustomerType.getId(), e);
		}

		//向水晶剑同步
		try
		{
			basCmCustomerTypeService.syncToSjj(basCmCustomerType);
		}
		catch (Exception e)
		{
			logger.info("向水晶剑同步客户异常,id=" + basCmCustomerType.getId(), e);
		}
	}

}

调用:

Runnable runnable = new CallbackCustomerTypeThread(basCmCustomerType, this);
		Thread thread = new Thread(runnable);
		thread.start();

第二种方式:通过变量或者方法传递参数

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(); 
} 
} 

第三种:通过回调函数传递参数

    暂时不写了,滴~~~~  下班卡

<think>好的,我现在要解决用户的问题:如何在Java中向Runnable的run方法传递参数。用户提到了他们之前提供的三个引用,需要参考这些内容来回答。首先,我需要回忆一下JavaRunnable接口的基本用法。Runnable接口只有一个run方法,而且这个方法是没有参数的,所以直接传递参数是不可能的。那怎么办呢? 用户提供的引用中提到了两种方法。引用[1]里提到自定义一个接口继承Runnable,并添加一个setParam方法。这样可以在创建实例后,通过setParam方法传递参数。引用[2]则是通过成员变量和setter方法来实现,比如在实现类里定义name变量,然后通过setName方法设置值,这样run方法就能访问到参数了。这两种方法看起来都是可行的,但具体应该如何实现呢? 另外,引用[3]提到了使用CyclicBarrier和线程池结合的方式,但这里可能更多是关于多线程同步的内容,和传参关系不大。不过用户的问题核心是传参,所以重点应该放在前两种方法上。 我需要先理清楚这两种方法的步骤。对于第一种方法,自定义接口MyRunnable继承Runnable,并添加setParam方法。然后具体的实现类需要实现这个接口,并在调用run之前设置参数。这种方法的好处是可以在创建实例之后灵活地传递参数,但需要自定义接口,可能增加代码的复杂性。 第二种方法是在实现类中定义成员变量,并提供setter方法。例如,MyThread2类有一个name成员变量,通过setName方法设置,然后在run方法中使用。这种方式更直接,不需要自定义接口,但需要在创建线程实例后调用setter方法,可能需要注意线程安全问题,比如在设置参数之后、线程启动之前确保参数已经正确设置。 除此之外,还有没有其他方法呢?比如通过构造函数传递参数。例如,在实现类的构造函数中接收参数,并保存为成员变量。这样在创建实例时就必须传入参数,避免了后续设置的需要。这可能也是一种常见的方法,用户提供的引用中没有提到,但可能也是一种有效的方式。 比如,可以定义一个类实现Runnable,构造函数接收参数,然后在run方法中使用。例如: public class MyRunnable implements Runnable { private String param; public MyRunnable(String param) { this.param = param; } public void run() { System.out.println(param); } } 然后使用时,new MyRunnable("hello"),并传递给Thread。这样参数在对象创建时就确定了,可能更安全,因为避免了在设置之后被修改的问题。但缺点是不够灵活,如果参数需要动态改变可能不太方便。 用户提供的引用中的两种方法,一种是自定义接口,另一种是setter方法,还有构造函数的方式。这三种方法各有优劣。需要根据具体情况选择。例如,如果参数在创建时已知,构造函数方式更简洁;如果需要在创建后设置,使用setter;如果希望更灵活的传参方式,可能自定义接口更好。 另外,用户提到的引用[1]中的自定义接口方法,可能还需要具体实现。比如,MyRunnable接口继承Runnable,并添加setParam方法。然后实现类需要实现这个方法,允许链式调用,例如: public interface MyRunnable extends Runnable { MyRunnable setParam(String... param); } public class MyRunnableImpl implements MyRunnable { private String[] params; @Override public MyRunnable setParam(String... param) { this.params = param; return this; } @Override public void run() { // 使用params } } 使用时,可以通过new MyRunnableImpl().setParam("a", "b")来传递参数。这种方式允许在创建实例后链式设置参数,可能更方便,但需要自定义接口和实现类,增加了代码量。 接下来需要比较这几种方法的适用场景。构造函数传参适合参数固定的情况;setter方法适合参数可能变化的情况;自定义接口可能用于需要灵活传参的复杂场景。用户的问题可能希望了解常见的几种实现方式,因此需要将这几种方法都涵盖进去。 另外,要注意线程安全问题。如果使用setter方法传递参数,需要确保在启动线程之前,参数已经被正确设置,否则可能导致run方法访问到未初始化的变量。例如,在引用[2]中,先调用setName,再启动线程,这样是安全的。但如果多个线程修改同一个Runnable实例的参数,可能会引发竞态条件,需要同步处理。 总结一下,可能的实现方式有: 1. 构造函数传参:在实现类的构造函数中接收参数,保存为成员变量,run方法中使用。 2. Setter方法:在实现类中定义setter方法,启动线程前调用setter设置参数。 3. 自定义接口:扩展Runnable接口,添加设置参数的方法,允许链式调用。 4. 匿名内部类:如果使用匿名内部类,可以直接在内部类中访问外部final变量,例如: String param = "hello"; new Thread(new Runnable() { public void run() { System.out.println(param); } }).start(); 这种方式在Java 8之前要求param是final的,Java 8之后可以隐式final。不过这可能属于另一种方式,通过闭包传递参数,但用户可能想知道这种方式是否可行。 用户提供的引用中没有提到这种方式,但这也是一种常见的方法。需要判断是否需要包含在回答中。可能用户的问题更关注于实现Runnable接口的类如何传参,而匿名内部类可能被视为另一种方式,但确实有效。 综合来看,用户的问题需要覆盖几种主要方法,并引用提供的例子。根据引用[1]和[2],重点介绍构造函数、setter方法和自定义接口的方式。同时,可以提到匿名内部类的方式,但可能属于lambda表达式或闭包的范畴。 现在需要组织回答的结构,确保清晰。首先说明Runnable的run方法本身没有参数,因此需要通过其他方式传递参数。然后分点介绍不同的方法,每种方法给出代码示例,并指出优缺点。最后总结如何选择合适的方法。 另外,用户提供的引用中有两个例子,一个是自定义接口,另一个是setter方法,需要结合这些例子进行说明。引用[3]可能不直接相关,但可以忽略。 在回答时,需要确保LaTeX格式正确,行内数学表达式用$...$,独立公式用$$...$$,但在这个问题中可能用不到数学公式,所以可能不需要处理这部分。但需要确保代码块正确,引用标识正确添加。 最后生成相关问题,可能涉及线程安全、各种方法的优缺点比较、实际应用场景等。</think>在Java中向Runnable的run()方法传递参数需要通过间接方式实现,因为run()方法本身没有参数。以下是三种常用方法及其实现细节: --- ### 方法一:构造函数传参(推荐) 通过实现类的构造函数直接传递参数,保证线程安全且代码简洁。 ```java public class MyRunnable implements Runnable { private final String param; // 使用final保证线程安全 public MyRunnable(String param) { this.param = param; } @Override public void run() { System.out.println("参数值: " + param); } } // 使用示例 Thread thread = new Thread(new MyRunnable("Hello")); thread.start(); ``` **优点**:线程安全,参数初始化后不可变。 **缺点**:参数需在创建对象时确定,灵活性较低[^2]。 --- ### 方法二:Setter方法传参 通过Setter方法动态设置参数,需注意线程启动前的时序控制。 ```java public class MyRunnable implements Runnable { private String param; public void setParam(String param) { this.param = param; } @Override public void run() { System.out.println("参数值: " + param); } } // 使用示例 MyRunnable task = new MyRunnable(); task.setParam("World"); // 必须在启动线程前设置 new Thread(task).start(); ``` **优点**:支持运行时动态修改参数。 **缺点**:需确保参数在调用start()前设置,否则可能引发空指针异常[^2]。 --- ### 方法三:自定义接口扩展Runnable 通过自定义接口实现链式传参,增强灵活性。 ```java public interface ParamRunnable extends Runnable { ParamRunnable setParam(String param); } public class CustomRunnable implements ParamRunnable { private String param; @Override public ParamRunnable setParam(String param) { this.param = param; return this; // 支持链式调用 } @Override public void run() { System.out.println("参数值: " + param); } } // 使用示例 new Thread(new CustomRunnable().setParam("Java")).start(); ``` **优点**:参数设置与对象创建解耦,支持链式编程。 **缺点**:需自定义接口,增加代码复杂度[^1]。 --- ### 方法四:匿名内部类(闭包特性) 利用Java的闭包特性直接访问外部变量。 ```java public class Main { public static void main(String[] args) { String param = "Anonymous"; new Thread(new Runnable() { @Override public void run() { System.out.println(param); // 变量需为final或等效final } }).start(); } } ``` **注意**:Java 8及以上版本支持隐式final变量,无需显式声明final。 --- ### 选择依据 1. **线程安全需求高**:优先使用构造函数传参。 2. **参数需动态修改**:选择Setter方法,但需注意时序。 3. **复杂传参场景**:自定义接口扩展Runnable。 4. **简化代码**:匿名内部类或Lambda表达式(Java 8+)。 ---
评论 9
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值