我正在使用spring和java。我有以下配置。
<bean id="taskExecutor"
class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
<property name="corePoolSize" value="5" />
<property name="maxPoolSize" value="10" />
<property name="waitForTasksToCompleteOnShutdown" value="true" />
</bean>
public class PrintTask implements Runnable{
String name;
public PrintTask(String name){
this.name = name;
}
@Override
public void run() {
Map<String, String> map = new HashMap<String, String>();
map.put(name + " is running", name + " is running");
Container.containerMap.put(this, map);
System.out.println(name + " is running");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(name + " is running");
}
}
public class PrintTaskTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring/applicationContext.xml");
ThreadPoolTaskExecutor taskExecutor = (ThreadPoolTaskExecutor) context.getBean("taskExecutor");
taskExecutor.execute(new PrintTask("Thread 1"));
taskExecutor.execute(new PrintTask("Thread 2"));
taskExecutor.execute(new PrintTask("Thread 3"));
taskExecutor.execute(new PrintTask("Thread 4"));
taskExecutor.execute(new PrintTask("Thread 5"));
//check active thread, if zero then shut down the thread pool
for (;;) {
int count = taskExecutor.getActiveCount();
System.out.println("Active Threads : " + count);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (count == 0) {
taskExecutor.shutdown();
break;
}
}
}
}
public class Container {
public static Map<PrintTask, Map<String,String>> containerMap = new HashMap<PrintTask, Map<String,String>>();
}
我的要求是:
我有几个线程调用相同的逻辑。在我的示例中,PrintTask由5个线程调用。无论何时调用逻辑,我都必须将值存储在映射中作为键值对。
Key = current Theread object
value = some Map
再次需要时,我可以传递当前线程并从地图中获取其值。
我做得对吗?
谢谢!
答案 0 :(得分:1)
public class Container {
private final static Map<PrintTask, Map<String, String>> values = new HashMap<>();
public static void putTaskToMap(PrintTask key, Map<String, String> values) {
synchronized(values) {
values.put(key, values);
}
}
public static Map<String, String> getValues(PrintTask key) {
syncronized (values) {
Map<String, String> retVal = values.get(key);
if(retVal == null) {
retVal = Collections.synchronizedMap(new HashMap<String, String>());
values.put(retVal);
}
return retVal;
}
}
}
public class PrintTask extends Runnable {
@Override
public void run() {
Map<String, String> map = Container.getValues(this);
map.put(name + " is running", name + " is running");
System.out.println(name + " is running");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(name + " is running");
}
public void someOtherMethod() {
Map<String, String> values = Container.getValues(this);
// the values here will always be the _same_ Map containing the same contents as the one in run.
}
重要的部分是:
Map
方法之外的run
。Map
不是实例绑定的(要么是static
,要么通过另一个类的共享实例访问)Map
的每次访问均为synchronized
。 (通过在方法头中使用Collections.synchronizedMap
或synchronized
关键字。)仔细阅读文档:
答案 1 :(得分:1)
根据您的要求,线程数要执行相同的逻辑,即PrintTask。那么有什么需要将PrintTask作为一个线程,为什么它不能是一个简单的类(单例)并将它传递给那些线程。并使用Lock或synchronized方法使PrintTask线程安全。所以你的PrintTask应该是这样的。
class PrintTask {
private Map map = Collections.synchronizedMap(new HashMap());
public synchronized void methodToBeExecutedByThread(String key, Map value) {
map.put(key, value);
}
public Map getMap() {
return map;
}
}
class PrintTaskThread {
private PrintTask task;
private String name;
public PrintTaskThread(PrintTask task, String name) {
this.task = task;
this.name = name;
}
public void run() {
Map map = Collections.synchronizedMap(new HashMap());
//populate map as requires
task.methodToBeExecutedByThread(name, map);
}
}
我建议不要使用Thread / Runnable作为地图的关键。而是在您的案例中创建线程时给出唯一键,线程名称将完成该任务。因此,如果您想要访问名称为“线程1”的线程正在使用的地图。您可以通过<Object of PrintTask>.getMap().get("Thread 1")
访问它。