Worker Thread Mode of Java Multithreading

  • 2021-12-05 05:59:04
  • OfStack

Directory 1. Worker Thread Pattern 2. Roles in Worker Thread Pattern 1. Client (Principal) 2. Channel (Communication Line) 3. Worker (Worker) 4. Request (Request) 3. Worker Thread Usage Scenario 4. Worker Thread Pattern Program Example

1. Worker Thread mode

Worker It means that people who work, in Worker Thread Mode, worker threads Worker thread Work is retrieved and processed one by one, and when all work is done, the worker thread waits for new work to arrive.

Worker Thread Patterns have also become Background Thread (Background thread) mode, and if we look at the place where multiple worker threads are stored, we can also call this mode Thread Pool Pattern.

2. Roles in the Worker Thread schema

1. Client (Principal)

Object that represents a work request Request And pass it to the Channel . In the sample program, ClientThread Equivalent to this role.

2. Channel (communication line)

Channel Role acceptance comes from Worker Thread0 Adj. Request And pass it to the Worker . In the sample program, Channel Equivalent to this role.

3. Worker (Workers)

Worker Role from Channel Get from Request And work, and when one job is finished, it will continue to get another Request In the sample program, WorkerThread Equivalent to this role.

4. Request (request)

Request A role is a role that represents a job, Request Role holds the information necessary to do the work. In the sample program, Request Equivalent to this role.

3. Worker Thread usage scenarios

Imagine a scene in which a factory is producing toys. In a workshop, there are several workers. Every time the production parts are ready, people outside the workshop put the parts on a table in the workshop. Every time the workers finish a toy, they take the parts from the table. Here, notice that the parts are not directly handed over to the workers. Another point is that the workers don't go home to change new people after finishing one part. The latter is a bit funny in reality, but it corresponds to a typical thread usage method in the program: thread pool.

The so-called thread pool is the reuse of threads. When threads finish tasks, they continue to take other tasks to execute, instead of destroying and starting new threads to execute other tasks. Because the start of the thread for the system performance overhead is relatively large, so it is very good for the improvement of system performance.

4. Worker Thread Mode Program Sample

The first is the request, that is, the parts of the toy


public class Request {

    private final String name;
    private final int number;

    public Request(String name, int number) {
        this.name = name;
        this.number = number;
    }

    public void execute(){
        System.out.println(Thread.currentThread().getName()+" executed "+this);
    }
    @Override
    public String toString() {
        return "Request=> " + "No." + number + "  Name." + name;
    }
}

That is, having name And number And execute Print out a simple class of fields when.

ClientThread Is responsible for putting the request into the RequestQueue Put the parts on the table.


public class ClientThread extends Thread {

    private static final Random random = new Random(System.currentTimeMillis());

    private final Channel channel;

    public ClientThread(String name, Channel channel) {
        super(name);
        this.channel = channel;
    }

    @Override
    public void run() {
        try {

            for (int i = 0; true; i++) {
                Request request = new Request(getName(),i);
                this.channel.put(request);
                Thread.sleep(random.nextInt(1_000));
            }
        } catch (Exception e) {

        }
    }
}

Channel class, can be used as a workshop


public class Channel {

    private final static int MAX_REQUEST = 100;

    private final Request[] requestQueue;
    private final WorkerThread[] workerPool;
    private int head;
    private int tail;
    private int count;

    public Channel(int workers) {

        this.requestQueue = new Request[MAX_REQUEST];
        this.head = 0;
        this.tail = 0;
        this.count = 0;
        this.workerPool = new WorkerThread[workers];
        this.init();
    }

    private void init() {
        for (int i = 0; i < workerPool.length; i++) {
            workerPool[i] = new WorkerThread("Worker-" + i, this);
        }
    }

    /**
     * push switch to start all of worker to work
     */
    public void startWorker() {
        Arrays.asList(workerPool).forEach(WorkerThread::start);

//        List<WorkerThread> workerThreads = Arrays.asList(workerPool);
//
//        workerThreads.stream().forEach(WorkerThread::start);
    }

    public synchronized void put(Request request) {
        while (count >= requestQueue.length) {
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        this.requestQueue[tail] = request;
        this.tail = (tail + 1) % requestQueue.length;
        this.count++;
        this.notifyAll();
    }

    public synchronized Request take() {
        while (count <= 0) {
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        Request request = this.requestQueue[head];
        this.head = (this.head + 1) % this.requestQueue.length;
        this.count--;
        this.notifyAll();
        return request;
    }
}

Requestqueue It can be used as a table and is a limited number of request queues. threadPool Is an array of 1 worker threads, which is a thread pool. Provided here putRequest And Worker Thread0 The method is to put the request into the request queue and take out the request, using the producer-consumer mode mentioned in the previous blog post Worker Thread1 Consumer producer mode of multithreaded design mode. Make sure WorkerThread And ClientThread We can cooperate amicably.

Worker thread:


public class WorkerThread extends Thread {

    private static final Random random = new Random(System.currentTimeMillis());
    private final Channel channel;

    public WorkerThread(String name, Channel channel) {
        super(name);
        this.channel = channel;
    }

    @Override
    public void run() {
        while (true) {
            channel.take().execute();

            try {
                Thread.sleep(random.nextInt(1_000));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

This is a process of continuously taking out the request from the request queue and then executing the request, which ensures the reuse of worker threads and will not be destroyed after executing a request task.

Finally, Main:


public class WorkerClient {

    public static void main(String[] args) {
        final Channel channel = new Channel(5);
        channel.startWorker();

        new ClientThread("Alex", channel).start();
        new ClientThread("Jack", channel).start();
        new ClientThread("William", channel).start();
    }
}

Results:

Worker-4 executed Request= > No.0 Name.Alex
Worker-2 executed Request= > No.0 Name.Jack
Worker-3 executed Request= > No.0 Name.William
Worker-4 executed Request= > No.1 Name.Jack
Worker-0 executed Request= > No.1 Name.William
Worker-3 executed Request= > No.2 Name.Jack
Worker-2 executed Request= > No.1 Name.Alex
Worker-4 executed Request= > No.2 Name.William
Worker-1 executed Request= > No.3 Name.Jack
Worker-3 executed Request= > No.2 Name.Alex
Worker-4 executed Request= > No.3 Name.William
Worker-0 executed Request= > No.4 Name.Jack
Worker-0 executed Request= > No.3 Name.Alex
Worker-1 executed Request= > No.5 Name.Jack
Worker-3 executed Request= > No.4 Name.William
Worker-1 executed Request= > No.6 Name.Jack
Worker-2 executed Request= > No.4 Name.Alex
Worker-3 executed Request= > No.7 Name.Jack
Worker-0 executed Request= > No.5 Name.William
Worker-1 executed Request= > No.5 Name.Alex
Worker-4 executed Request= > No.8 Name.Jack
Worker-2 executed Request= > No.6 Name.Alex
Worker-0 executed Request= > No.7 Name.Alex
Worker-4 executed Request= > No.8 Name.Alex
Worker-2 executed Request= > No.6 Name.William
Omit...

You can see that the thread on which the thread executes the task is WorkerThread1,2,3,4,5 5, which are continuously executed from ClientThread Alex , Jack , William The requested task of.


Related articles: