java: concurrent programming model -Callable and Future

Their understanding of thread pool:

coresize 3

maxsize 5

blockLinkedQuenue 3

When the task submitted <= 3, create three threads work

Greater than 3, the task to join the queue blocking, when the core thread has free will to carry out their task execution queue thread is actually running multiplexing is performed

If the latter have submitted many tasks, the queue does not fit, go ahead and create a new thread to execute them if the task has been greater than the> queue maximum number of threads +, inability to work, and only collapsed, throwing refuse abnormal

First, the rational allocation of thread pool

CPU -intensive

CPU-intensive means that the task requires a lot of computation, without obstruction, CPU runs at full speed.

CPU intensive tasks only likely to be accelerated (by multiple threads) on the true multi-core CPU, and CPU on a single core, multi-threaded whether you open several simulations, the task can not be accelerated, because the total CPU operation capacity on those.

IO -intensive

IO-intensive, that is, the task requires a lot of IO, that is a lot of congestion. IO-intensive tasks running on a single thread will lead to waste a lot of CPU power wasted in waiting. So using the IO-intensive tasks in a multi-threaded program can greatly accelerate the run, on a real-time single-core CPU, this acceleration is mainly the use of the blocking time is wasted.

Then on a thread pool explore the left tail, how to set the thread pool size.

To a reasonable allocation of the thread pool size, must first analyze the characteristics of the task, it can be analyzed from the following perspectives:

1. The nature of the tasks: the CPU-intensive tasks, IO-intensive tasks, the hybrid mission.

2. The priority of the task: high, medium and low.

3. The execution time of the task: long, medium and short.

4. dependent tasks: dependent on whether the other system resources, such as database access.

The nature of the task can be different to different sizes of thread pool to perform.

For the different nature of the task is, CPU-intensive tasks should be configured as small threads, such as the number of threads to configure the number of CPU +1, IO-intensive tasks should be configured with as many threads as IO operations do not take up CPU, Do not let the CPU retired and sit, should increase the number of threads, such as CPU configuration +1 double the number, and for the hybrid mission, if you can split, split into IO-intensive and CPU-intensive processing, respectively, provided that two time's running is about the same, if the processing time is a big difference, it is not necessary to split up.

If the task has dependencies on other system resources, such as a task dependent on the results of the database connection is returned, this time the longer the waiting time, the CPU is idle longer period of time, then the greater the number of threads should be set in order to better using the CPU.

Of course, specific and reasonable value thread pool size, requires a combination of the actual situation of the system, in order to obtain relatively large number of attempts, more than just a summary of the previous law.

The optimum number of threads = ((thread thread CPU time latency +) / thread CPU) * Number of CPU

Each thread such as average CPU time is 0.5s, and the thread is waiting time (non-CPU time, such as IO) to 1.5s, CPU core is 8, then the estimate obtained based on the formula above: ((0.5 + 1.5) / 0.5) * 8 = 32. This formula is further converted to:

The optimum number of threads = (thread waiting thread CPU time ratio + 1) * Number of CPU

Can draw a conclusion:  thread wait the higher the percentage, the more the need to thread. Thread CPU time the higher the proportion, the less need thread.  More than the previous formula the number of CPU and IO-intensive tasks set thread basically.

When the CPU-intensive tasks to configure a small number of threads, and probably quite a few cpu core machines, so that each thread can perform tasks in

When the IO-intensive, most of the threads are blocked, they need to configure multi-thread count, 2 * cpu audit

The operating system name explanation:

Some progress has spent most of the time on a computer, while others are waiting on I / O spent most of the time,

The former is called computationally intensive ( the CPU-intensive) computer-bound, which is called I / O intensive, I / O-bound.

wait:

1) When a thread is in wait () status, that is waiting holdings object's monitor to be released before it, () methods notify lets the thread is active again, so go grab the object's monitor, wake up the thread.
(2) If multiple threads in a wait state, then a call to notify () method can only wake a random thread.
(3) At the same time, only one thread can obtain the object's monitor, after the execution is completed, then release it for use by other threads preempted.

Callable

In Java, create a thread there are two ways, one is the Thread class inheritance, one is to achieve Runnable interface. However, the disadvantage of these two methods is that at the end of a thread of execution tasks, the results can not be obtained. We generally only use shared variables or shared memory and thread communication means to achieve the purpose of obtaining results of the task. However, the Java, but also provided the use of Callable and Future operations to achieve access to the results of the task. Callable task to perform, produce results, and Future to get results.

Are Callable interface is similar to Runnable interface, view the source code, you can see Callable interface defined as follows:

 

@FunctionalInterface

public interface Callable<V> {

    /**

     * Computes a result, or throws an exception if unable to do so.

     *

     * @return computed result

     * @throws Exception if unable to compute a result

     */

    V call() throws Exception;

}

 

Can be seen, the Runnable interface differs in that, with a generic method Call return value V.

Future common method

V get (): Gets the results of asynchronous execution, if no results are available, this method will block until the asynchronous computation is complete.

GET V (Long timeout, TimeUnit Unit) : Gets the asynchronous execution result, if no results are available, this method will block, but there is a time limit, if the blocking time exceeds the set timeout time, the method throws an exception.

boolean isDone (): if the task execution ends, either end or canceled during normal or abnormal, return true.

boolean isCanceller (): the former is canceled if the task is completed, it returns true.

boolean cancel (boolean mayInterruptRunning): If the task has not started, execute cancel (...) method returns false; if the task has already started, execution cancel (true) method to perform this task will interrupt threads to try to stop the task, If you stop successful, return true; when the task has been started, execute cancel (false) method will have no effect on the task executing thread (thread to normal execution to completion), then return false; when the task has been completed, execution cancel (...) method returns false. mayInterruptRunning parameter indicates whether to interrupt the execution threads.

We also know that by the method of analysis actually Future provides three functions: (1) able to interrupt the task execution (2) to determine whether to perform task completion (3) Obtain the complete amount of task execution results.

 

We appreciate the use of a simple example of the use of Callable and Future to get the results of the task.

 

 

public class TestMain {

public static void main(String[] args) throws InterruptedException, ExecutionException {

ExecutorService executor = Executors.newCachedThreadPool();

Future<Integer> future = executor.submit(new AddNumberTask());

. System OUT .println (. The Thread currentThread () .getName () + " thread performs other tasks " );

Integer integer = future.get();

System.out.println(integer);

// close the thread pool

if (executor != null)

executor.shutdown();

}

 

}

 

class AddNumberTask implements Callable<Integer> {

 

public AddNumberTask() {

 

}

 

@Override

public Integer call() throws Exception {

System.out.println("####AddNumberTask###call()");

Thread.sleep(5000);

return 5000;

}

 

}

Future Mode

Future模式的核心在于:去除了主函数的等待时间,并使得原本需要等待的时间段可以用于处理其他业务逻辑

Futrure模式:对于多线程,如果线程A要等待线程B的结果,那么线程A没必要等待B,直到B有结果,可以先拿到一个未来的Future,等B有结果是再取真实的结果。

 在多线程中经常举的一个例子就是:网络图片的下载,刚开始是通过模糊的图片来代替最后的图片,等下载图片的线程下载完图片后在替换。而在这个过程中可以做一些其他的事情。

 

首先客户端向服务器请求RealSubject,但是这个资源的创建是非常耗时的,怎么办呢?这种情况下,首先返回Client一个FutureSubject,以满足客户端的需求,于此同时呢,Future会通过另外一个Thread 去构造一个真正的资源,资源准备完毕之后,在给future一个通知。如果客户端急于获取这个真正的资源,那么就会阻塞客户端的其他所有线程,等待资源准备完毕。

 

公共数据接口,FutureData和RealData都要实现。

public interface Data {

public abstract String getRequest();

}

 

FutureData,当有线程想要获取RealData的时候,程序会被阻塞。等到RealData被注入才会使用getReal()方法。

 

public class FurureData implements Data {

 

public volatile static boolean ISFLAG = false;

private RealData realData;

 

public synchronized void setRealData(RealData realData) {

// 如果已经获取到结果,直接返回

if (ISFLAG) {

return;

}

// 如果没有获取到数据,传递真是对象

this.realData = realData;

ISFLAG = true;

// 进行通知

notify();

}

 

@Override

public synchronized String getRequest() {

while (!ISFLAG) {

try {

wait();

} catch (Exception e) {

 

}

}

// 获取到数据,直接返回

return realData.getRequest();

}

 

}

真实数据RealData

public class RealData implements Data {

private String result;

 

public RealData(String data) {

System.out.println("正在使用data:" + data + "网络请求数据,耗时操作需要等待.");

try {

Thread.sleep(3000);

} catch (Exception e) {

 

}

System.out.println("操作完毕,获取结果...");

result = "余胜军";

}

 

@Override

public String getRequest() {

return result;

}

 

FutureClient  客户端

 

public class FutureClient {

 

public Data request(String queryStr) {

FurureData furureData = new FurureData();

new Thread(new Runnable() {

 

@Override

public void run() {

RealData realData = new RealData(queryStr);

furureData.setRealData(realData);

}

}).start();

return furureData;

 

}

 

}

调用者:

 

public class Main {

 

public static void main(String[] args) {

FutureClient futureClient = new FutureClient();

Data request = futureClient.request("请求参数.");

System.out.println("请求发送成功!");

System.out.println("执行其他任务...");

String result = request.getRequest();

System.out.println("获取到结果..." + result);

}

 

}

调用者请求资源,client.request("name"); 完成对数据的准备

当要获取资源的时候,data.getResult() ,如果资源没有准备好isReady = false;那么就会阻塞该线程。直到资源获取然后该线程被唤醒。

Guess you like

Origin www.cnblogs.com/hejunhong/p/11546278.html