0

我正在使用spring和java。我有以下配置。

应用程序上下文.xml

<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>

打印任务.java

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

}

PrintTaskTest.java

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

        }
}

容器.java

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

再次,当需要时,我可以传递当前线程并从地图中获取其值。

我做得对吗?

谢谢!

4

2 回答 2

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.
}

重要的部分是:

  1. 你有你的方法的Map外部。run
  2. Map的不是实例绑定(它是static或者它是通过另一个类的共享实例访问的)
  3. 那就是每一次访问Map都是synchronized。(通过使用Collections.synchronizedMap或通过synchronized方法头中的关键字。)

仔细阅读文档:

  1. 同步的
  2. Collections.synchronizedMap()
于 2013-10-15T07:51:21.813 回答
1

根据您的要求,线程数希望执行相同的逻辑,即 PrintTask。那么有什么需要将 PrintTask 作为线程,为什么不能是一个简单的类(单例)并将其传递给那些线程。并使用 Lock 或同步方法使 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 作为地图的关键。相反,当您在您的情况下创建线程时会提供唯一键,线程名称将完成这项工作。因此,如果您想访问名称为“Thread 1”的线程正在使用的映射。您可以通过<Object of PrintTask>.getMap().get("Thread 1").

于 2013-10-15T08:06:16.607 回答