根据Id配置子线程

时间:2017-01-17 12:48:43

标签: java multithreading

我从用户收到数据时生成子线程。

如果我想在同一用户再次发送数据并希望再次生成新的用户子线程时,我想处置以前的用户子线程,有哪些步骤?

3 个答案:

答案 0 :(得分:3)

是的,因此java无法处理线程,线程只会运行直到它终止。 所以: 为了摆脱线程,你需要允许线程run方法结束,然后去除对Thread及其构造的所有Runnable的所有引用。

你想切换完成的线程,这是一个简单的例子:

class SimpleRunnable implements Runnable {
public volatile boolean run = true;  //Volatile for thread safety.

public void run() {
        while(run) {
                System.out.println("WHOOOO!"); //Boy, will this be annoying     
        }
    }
}

从此runnable创建一个线程:

SimpleRunnable run = new SimpleRunnable();
Thread thread = new Thread(run);  
Thread.start(); //run thread
//Stop thread 
run.run=false;
//Thread will be removed when out of scope

您需要在您的情况下为每个用户创建一个Runnable,然后在创建新线程时调用set stop变量。 例如,您可以通过userId将每个runnable存储在ConcurrentHashMap中。

ConcurrentHashMap<String,SimpleRunnable> runnablesByUser = new ConcurrentHashMap<>();

public void startNewThreadForUser(String userId){
//Time passes, retrieve and kill old thread:
SimpleRunnable oldRunnable = runnableByUser.get(userId);
if(oldRunnable!=null){
   oldRunnable.run=false;
}
SimpleRunnable newRunnableUserOne = new SimpleRunnable();
runnablesByUser.put(userId,newRunnableUserOne);
Thread thread = new Thread(newRunnableUserOne);
thread.start();
}

如果找到该方法,则调用该方法将终止旧线程,通过将其替换为ConcurrentHashMap中的新线程从范围释放旧线程,最后启动新线程。 像这样:

public void startThreeThreads(){
    startNewThreadForUser("User1");//starts Thread for User1
    startNewThreadForUser("User2");//starts Thread for User2
    startNewThreadForUser("User1");//Replaces Thread for User1
}

管理正在运行的线程通常是在一个线程池中完成的,这在各种方面都很粗糙,但希望它很有用。

如果你愿意,我可以详细说明这个机制。

答案 1 :(得分:2)

每次从用户接收数据时启动新线程都会导致资源耗尽,此外还会导致管理太多线程的不必要开销。您的计算机具有有限数量的线程,可以在任何时间运行并受CPU限制。找出那个号码你可以使用命令

Runtime.getRuntime().availableProcessors()

另一方面,如果要处理的作业需要大量的I / O处理,则应该启动多个线程而不是&#34; Runtime.getRuntime()。availableProcessors()&#34; ,或者你的CPU使用率不足。

我要做的是使用&#34; ExecutorService&#34;它将为您处理线程(无需手动启动,停止线程)。只需启动一个&#34; ExecutorService&#34;使用您希望同时执行的线程总数,然后每次从User获得更多工作时,将新任务(作为Callable)提交给ExecutorService。 executorService将为您处理该任务的执行,一旦完成,它将可用于垃圾收集。

例如,请参阅以下代码:

import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class MultipleClientsExample {

    public static final int TOTAL_THREADS_TO_PROCESS_CUSTOMER_WORK = 4;

    public static final Random random = new Random();
    public static int customerCounter = 0;


    public static void main(String[] args) throws InterruptedException {
        MultipleClientsExample multipleClientsExample = new MultipleClientsExample();
        multipleClientsExample.doTheWork();
    }

    private void doTheWork() throws InterruptedException {

        ExecutorService executorService = Executors.newFixedThreadPool(TOTAL_THREADS_TO_PROCESS_CUSTOMER_WORK);

        while (customerCounter < 10) {

            try {
                CustomerInput customerInput = getWorkFromCustomer();
                System.out.println("main program. received work from customer: " + customerInput.getCustomerId());
                executorService.submit(new WorkToBeDone(customerInput.getCustomerId(), customerInput.getWorkInfo()));
            } catch (InterruptedException e) {
                break;
            }
            customerCounter++;
        }
        executorService.shutdown();
        executorService.awaitTermination(5, TimeUnit.SECONDS);

    }

    private CustomerInput getWorkFromCustomer() throws InterruptedException {

        while (true) {

            String customerId = String.valueOf(random.nextInt(10));
            CustomerInput customerInput = new CustomerInput(customerId, "work from customer: " + customerId);
            return customerInput;
        }
    }
}

class WorkToBeDone implements Callable<Void> {

    private String clientId;
    private String workInfo;

    public WorkToBeDone(String clientId, String workInfo) {
        this.clientId = clientId;
        this.workInfo = workInfo;
    }


    @Override
    public Void call() throws Exception {
        System.out.println("inside a working thread: it is going to do the work of customer: " + clientId);
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            System.out.println("worker processing job from customer: " + clientId + " was interrupted. ending now");
            return null;
        }

        System.out.println("work completed for customer: " + clientId);
        return null;
    }
}

class CustomerInput {

    private String customerId;
    private String workInfo;


    public CustomerInput(String customerId, String workInfo) {
        this.customerId = customerId;
        this.workInfo = workInfo;
    }

    public String getCustomerId() {
        return customerId;
    }

    public String getWorkInfo() {
        return workInfo;
    }
}

答案 2 :(得分:2)

如果您希望能够取消已提交给线程池的任务,则必须继续引用每个任务的Future值,并确保删除已完成的任务的引用,你取消了,所以他们准备被垃圾收集(否则你会有内存泄漏)。

例如

import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

public class MultipleClientsExample {

    public static final int TOTAL_THREADS_TO_PROCESS_CUSTOMER_WORK = 4;

    public static int customerCounter = 0;


    public static void main(String[] args) throws InterruptedException {
        MultipleClientsExample multipleClientsExample = new MultipleClientsExample();
        multipleClientsExample.doTheWork();
    }

    private void doTheWork() throws InterruptedException {

        final ExecutorService executorService = Executors.newFixedThreadPool(TOTAL_THREADS_TO_PROCESS_CUSTOMER_WORK);

        Map<String, Future<String>> map = new ConcurrentHashMap<>();

        while (customerCounter < 11) {

            try {
                WorkToBeDone workToBeDone = getWorkFromCustomer();
                System.out.println("main program. received work from customer: " + workToBeDone.getClientId());

                Future<String> resultFuture = executorService.submit(workToBeDone);
                map.put(workToBeDone.getClientId(), resultFuture);

            } catch (InterruptedException e) {
                break;
            }
            customerCounter++;

        }


        // cancel job of customer with id: 10

        Future<String> resultFuture = map.get("10");
        System.out.println("cancelling job of customerId: 10");
        resultFuture.cancel(true);


        // remove references of all completed jobs

        Thread.sleep(2000);

        System.out.println("looking for jobs that completed or were cancelled.");
        Iterator<Map.Entry<String, Future<String>>> iterator = map.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, Future<String>> entry = iterator.next();
            if (entry.getValue().isCancelled() || entry.getValue().isDone()) {
                System.out.println("removing reference of job for customer: " + entry.getKey());
                iterator.remove();
            }
        }

        // simpler way to remove entries from map (but doesn't print output of jobs removed from map)
        // map.entrySet().removeIf(entry -> entry.getValue().isCancelled() || entry.getValue().isDone());


        executorService.shutdown();
        executorService.awaitTermination(5, TimeUnit.SECONDS);

    }

    private WorkToBeDone getWorkFromCustomer() throws InterruptedException {
        String customerId = String.valueOf(customerCounter);
        WorkToBeDone workToBeDone = new WorkToBeDone(customerId, "work from customer: " + customerId);
        return workToBeDone;
    }
}


class WorkToBeDone implements Callable<String> {

    private String clientId;
    private String workInfo;


    public String getClientId() {
        return clientId;
    }

    public WorkToBeDone(String clientId, String workInfo) {
        this.clientId = clientId;
        this.workInfo = workInfo;
    }


    @Override
    public String call() throws Exception {
        System.out.println("inside a working thread: it is going to do the work of customer: " + clientId);
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            System.out.println("worker processing job from customer: " + clientId + " was interrupted. ending now");
            return clientId;
        }

        System.out.println("work completed for customer: " + clientId);
        return clientId;
    }
}