This is the 25th day of my participation in the August Genwen Challenge.More challenges in August

preface

Accumulate a little bit every day, product short step to thousands of miles. Today we will learn Condition, Callable&Future in JUC package.

Condition waits and wakes up

  • JUCThe purpose of providing so many utility classes is to allow us to control the thread in the multithreaded environment of the application,ConditonObject that causes specified threads to wait and wake up in the expected order. In plain English, we have complete control over the order in which threads are executed.Note:It must be andReentrantLockReentrant lock is used together.
  • ConditionUsed to replacewait()/notify()methods
    • notifyCan only wake up waiting threads randomly, whileConditionThe specified thread can be woken up, which is beneficial for better control of concurrent programs.

Condition core method

  • await()Blocks the current thread until signal() wakes up
  • signal()Awaken theawait()The thread continues execution from the interrupt
  • signalAll()Wake up all the deadawait()Blocked thread

Code sample

  • Create three threads to print separately1,2,3, added for obvious effect1000msSleep. Normally printing in sequence is definitely1,2,3
  • But now we want to print3,1,2, then you can useConditionTo implement control, look at the following code
public class ConditionSample {

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

        ReentrantLock lock = new ReentrantLock();
        Condition c1 = lock.newCondition();
        Condition c2 = lock.newCondition();

        new Thread(() -> {
            lock.lock();
            try {
                c1.await();// Block the current thread
                Thread.sleep(1000);
                System.out.println(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }).start();

        new Thread(() -> {
            lock.lock();
            try {
                c2.await();// Block the current thread
                Thread.sleep(1000);
                System.out.println(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }).start();

        new Thread(() -> {
            lock.lock();
            try {
                Thread.sleep(1000);
                System.out.println(3);
                c1.signal();
                c2.signal();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally{ lock.unlock(); } }).start(); }}Copy the code

We created two Condition objects, C1 and C2, using the ReentrantLock object. It is equivalent to two marked locks, which are respectively added to the thread of printing 1 and 2. After the printing of 3 is completed, the thread can control which one to wake up first, and which one to print out to achieve the desired effect.

Callable&Future

  • Callable is used to create threads just like Runnable, except that Callable has a return value and can throw an exception
  • A Future is an interface. It is used to represent the result of asynchronous computation. Provides a way to check that a calculation is complete, wait for it to complete, and get the results of the calculation.

Code sample

Get all primes up to 10000, single thread loop search method is not introduced here, look at the following example code, we can use multiple threads to determine whether it is prime, and then receive the result back. The method of obtaining prime numbers here is relatively simple, and the efficiency advantage of multithreading becomes obvious if you switch to more complex logic.

public class FutureSample {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        for (int i = 2; i <= 10000; i++) {
            Computor c = new Computor();
            c.setNum(i);
            Future<Boolean> result = executorService.submit(c);
            try {
                Boolean r = result.get();
                if(r) { System.out.println(c.getNum()); }}catch(InterruptedException | ExecutionException e) { e.printStackTrace(); } } executorService.shutdown(); }}class Computor implements Callable<Boolean> {
    private Integer num;
    public Integer getNum(a) {
        return num;
    }
    public void setNum(Integer num) {
        this.num = num;
    }
    @Override
    public Boolean call(a) throws Exception {
        boolean isprime = true;
        for (int i = 2; i < num; i++) {
            if (num % i == 0) {
                isprime = false;
                break; }}returnisprime; }}Copy the code
  • FutureIs listening on the thread used for the calculation, because the calculation is performed in another thread, so the process of returning the result is asynchronous
  • executorService.submit(c);willcObject is submitted to the thread pool and executed immediately if there are idle threadscallmethods
  • result.get();Used to get the return value if the thread is internalcallIf the execution is not complete, it enters the wait state until the calculation is complete