Java 併發編程學習筆記(16) ----CompletionService

CompletionService

1.1 CompletionService 的功能

CompletionService的功能就是以異步的方式,一邊產生新的任務,一邊處理已完成任務的結果。 
CompletionService主要解決一個什麼問題呢? 
    Future 接口調用get()方法取得處理的結果,但是這個方法是阻塞性的,如果調用get()
方法時,任務尚未執行完成,get方法會一直阻塞到此任務執行完成爲止。這樣的後果就是一旦前面
的任務耗時太長,後面的任務的get()方法就會排隊等待,影響相率。
    使用CompletionService可以按照完成這些任務的時間順序處理他們的結果。

1.2 代碼


package com.lhc.concurrent.completion.nonBlock;

import com.google.common.collect.Lists;

import java.util.ArrayList;
import java.util.concurrent.*;

public class MyCallable implements Callable<String>{
    private String userName;
    private long sleepTime;

    public MyCallable(String userName, long sleepTime) {
        this.userName = userName;
        this.sleepTime = sleepTime;
    }

    @Override
    public String call() throws Exception {
        System.out.println(userName);
        Thread.sleep(sleepTime);
        return "return " + sleepTime;
    }

    public static void main(String[] args) throws Exception{
        MyCallable name1 = new MyCallable("name1", 1050);
        MyCallable name2 = new MyCallable("name2", 1040);
        MyCallable name3 = new MyCallable("name3", 1030);
        MyCallable name4 = new MyCallable("name4", 1020);
        MyCallable name5 = new MyCallable("name5", 1010);

        ArrayList<Callable> callables = Lists.newArrayList();
        callables.add(name1);
        callables.add(name2);
        callables.add(name3);
        callables.add(name4);
        callables.add(name5);

        ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 5, 5,
                TimeUnit.SECONDS, new LinkedBlockingDeque<Runnable>());
        ExecutorCompletionService completionService = new ExecutorCompletionService(executor);

        for (int i = 0; i < callables.size(); i++) {
            completionService.submit(callables.get(i));
        }

        for (int i = 0; i < 5; i++){
            /**
             * 哪個任務先執行完,那個任務的返回值就先打印,解決了Future 阻塞的特點
             * 但是如果沒有任何任務被執行完,則.take().get()方法還是呈阻塞特性。
             */
            System.out.println(completionService.take().get());
        }
    }
}

1.3測試結果

name1
name5
name2
name3
name4
return 1010
return 1020
return 1030
return 1040
return 1050

2.1 Future submit(Runnable task, V result)方法

另外一種使用姿勢

2.2 代碼


public class User {
    private String name;
    private String password;

    public User(String name, String password) {
        super();
        this.name = name;
        this.password = password;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}


package com.lhc.concurrent.completion.submit;

import java.util.concurrent.*;

public class MyRunnable implements Runnable{
    private User user;

    public MyRunnable(User user) {
        super();
        this.user = user;
    }

    @Override
    public void run() {
        user.setName("jt");
        user.setPassword("pwd");
        System.out.println("running end");
    }

    public static void main(String[] args) throws Exception{
        User user = new User("name", "pwd");
        MyRunnable myRunnable = new MyRunnable(user);

        ExecutorService executorService = Executors.newCachedThreadPool();
        ExecutorCompletionService completionService = new ExecutorCompletionService(executorService);
        Future<User> submit = completionService.submit(myRunnable, user);
        System.out.println(submit.get().getName() + " " + submit.get().getPassword());
    }
}


2.3 運行結果

running end
jt pwd

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章