Java multithreading JUC

1. Volatile keyword

During multi-threaded access, a serious problem is that the memory is invisible. In fact, during memory access, each thread has its own buffer. Each time it makes changes, it accesses the data from the main memory, then puts it into its own buffer, and puts it back into the main memory after making changes. In this way, the variables between each thread are invisible. The read data may always be wrong, so there is a keyword to make the shared variable transparent. It's like all operations are directly in memory, because it keeps synchronizing the data in main memory.

In fact, the operation of I + + is a temporary variable at the bottom. In this way, although it is an expression, there will be security problems in multithreading.

package atomic;

/**
 * @Author: lwen
 * @Date: Created in 2017/8/19 15:26
 * @Description:
 */

class Test implements Runnable{
    private volatile int i=0;
    @Override
    public void run() {
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(i++);
    }
}
public class Main {
    public static void main(String[] args) {
        Test t=new test();
        for (int i = 0; i < 10; i++) {
            new Thread(t).start();
        }
    }
}

The result of the final run is obviously the keyword volatile. It only allows variable courseware to operate in main memory, but it has no mutually exclusive function. In short, there is no lock to control. They all get the data from main memory in time, but they get the latest data. Someone submitted the result while calculating, so it leads to repeated elements. The most fundamental reason is that I + + has three operations: read, operation and write

1 3 2 0 4 7 6 5 8 8 Process finished with exit code 0

The Java bottom layer provides some atomic variables, such as atomicinteger. Since they are derived from, they are visible first. The bottom layer of these things mainly uses the CAS (compareandset) algorithm, which is mainly the hardware support provided by the operating system. This algorithm has three important parameters: the first is V, which is the value read from memory before operation, the value read from memory before writing, and the value to be written to B. Make a judgment before writing, and write B only when v = = a, otherwise do nothing.

3. Concurrenthahsmap secure HashMap

This is a thread safe HashMap. The thread safe HashMap naturally has hashtables, but this efficiency is very low, mainly because its blocking granularity is too large. It locks the entire hashtable, that is, two irrelevant hashtables are mutually exclusive. In jdk1 In the future, concurrent hahsmap was used. At that time, the lock segmentation mechanism was mainly used, that is, the hashtable was divided into 16 segments based on the original, and each segment corresponds to a HashMap. In this way, two unrelated hashmaps can be accessed synchronously.

4. Countdownlatch locking

The so-called locking means that the thread will wait until the code of all threads is running. Its underlying implementation is to maintain a variable, which is the number of threads currently alive. When it is reduced to 0, that is, other threads are running, the locking thread can start. For example, if we open ten threads to do something, we count the total running time of these ten threads in the main thread.

package latch;

import com.sun.javafx.sg.prism.web.NGWebView;

import java.util.concurrent.CountDownLatch;

/**
 * @Author: lwen
 * @Date: Created in 2017/8/19 16:06
 * @Description:
 */
class Latch implements Runnable{
    private CountDownLatch latch;

    public Latch(CountDownLatch latch) {
        this.latch = latch;
    }

    @Override
    public void run() {
        System.out.println(Thread.currentThread());
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        latch.countDown();  //线程结束以后,需要给维护的变量减一
    }
}

public class Main {
    public static void main(String[] args) throws InterruptedException {
        int start= (int) System.currentTimeMillis();
        CountDownLatch downLatch= new CountDownLatch(10);  //定义十个线程
        Latch latch=new Latch(downLatch);
        for (int i = 0; i < 10; i++) {
            new Thread(latch).start();
        }
        downLatch.await();  //当线程没有完全结束的时候,主线程需要等待
        int end= (int) System.currentTimeMillis();
        System.out.println(end-start);
    }
}

4. The third way to create a thread

Generally, when we create threads, we inherit the thread class or implement the runnable interface, but we mainly use the runnable interface. However, pay attention to these two methods to make things that have no return value. That is, we can't multithread and can't return some results. The third way to create a thread, that is, to get the return value, is to use the callable interface. The use of this interface requires the futuretask class, which implements the runnable and future interfaces. Its specific use method is a little different from the runnable interface.

package future;

import org.omg.PortableInterceptor.INACTIVE;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

/**
 * @Author: lwen
 * @Date: Created in 2017/8/19 16:23
 * @Description:
 */
class Future implements Callable<Integer>{

    @Override
    public Integer call() throws Exception {
        int sum=0;
        for (int i = 0; i < 1000; i++) {
            sum+=i;
        }
        return sum;
    }
}

public class Main {
    public static void main(String[] args) throws ExecutionException,InterruptedException {
        Future future=new Future();
        FutureTask<Integer> task=new FutureTask<Integer>(future);
        new Thread(task).start();

        System.out.println(task.get());;//获取最终的返回值,但是注意这个地方的这个方法其实就是一个闭锁,前面的那个县城没有执行完,这个地方是不会执行的
    }
}

5. Advanced synchronization

There are three ways to solve the synchronization problem: synchronization code block, synchronization function, and synchronization lock. That is, manually declare lock and then use unlock to release the lock

package lock;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.reentrantlock;

/**
 * @Author: lwen
 * @Date: Created in 2017/8/19 16:33
 * @Description:
 */

class Ticket implements Runnable{
    private int ticket=100;
    Lock lock=new reentrantlock();
    @Override
    public void run() {
        while (true) {
            lock.lock();
            try {
                if (ticket != 0) {
                    try {
                        Thread.sleep(20);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    ticket--;
                    System.out.println(Thread.currentThread().getName() + ":" + ticket);

                }
            }finally {
                lock.unlock();  //解锁必须放在finally里面保证能够执行到
            }
        }
    }
}

public class Main {
    public static void main(String[] args) {
        Ticket t=new Ticket();
        new Thread(t,"窗口一").start();
        new Thread(t,"窗口二").start();
        new Thread(t,"窗口三").start();
    }
}

6. Thread synchronization between producers and consumers

package product;

import java.util.logging.Level;

/**
 * @Author: lwen
 * @Date: Created in 2017/8/19 16:57
 * @Description:
 */
class Clerk {
    private int production=0;

    public synchronized void get() throws InterruptedException {
        while (production>=1){  //notifyAll 可能会形成假唤醒问题,所以说必须要使用while一直判断而不能使用if
            System.out.println("已满");
            this.wait();
        }
        System.out.println(Thread.currentThread().getName()+":"+ ++production);
        this.notifyAll();

    }

    public synchronized void sale() throws InterruptedException {
        while (production<=0){
            System.out.println("卖完");
            this.wait();
        }
        System.out.println(Thread.currentThread().getName()+":"+ --production);
        this.notifyAll();

    }
}


class Product implements Runnable{
    private Clerk clerk;

    public Product(Clerk clerk) {
        this.clerk = clerk;
    }

    @Override
    public void run() {
        for (int i = 0; i < 20; i++) {
            try {
                Thread.sleep(20);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            try {
                clerk.get();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

class Consumer implements Runnable{
    private Clerk clerk;

    public Consumer(Clerk clerk) {
        this.clerk = clerk;
    }

    @Override
    public void run() {
        for (int i = 0; i < 20; i++) {
            try {
                Thread.sleep(20);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            try {
                clerk.sale();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
public class Main {
    public static void main(String[] args) {
        Clerk clerk=new Clerk();
        Product p=new Product(clerk);
        Consumer consumer=new Consumer(clerk);
        new Thread(p,"生产者1").start();
        new Thread(p,"生产者2").start();
        new Thread(consumer,"消费者1").start();
        new Thread(consumer,"消费者2").start();
    }
}

7. Read write lock

Exclude writing and reading and writing at the same time

package readandwrite;

import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.reentrantreadwritelock;

/**
 * @Author: lwen
 * @Date: Created in 2017/8/19 17:29
 * @Description:
 */

class ReadWriteLockDemo {
    private int number=0;
    private ReadWriteLock lock=new reentrantreadwritelock();

    public void read(){
        lock.readLock().lock();
        try {
            System.out.println(Thread.currentThread().getName()+":"+number);
        }finally {
            lock.readLock().unlock();
        }
    }

    public void write(int number) throws InterruptedException {
        lock.writeLock().lock();
        Thread.sleep(20);
        try {
            this.number=number;
            System.out.println("write");
        }finally {
            lock.writeLock().unlock();
        }
    }
}

public class Main {
    public static void main(String[] args) {
        ReadWriteLockDemo readWriteLockDemo=new ReadWriteLockDemo();
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    readWriteLockDemo.write(20);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();

        for (int i = 0; i < 20; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    readWriteLockDemo.read();
                }
            }).start();
        }
    }
}

4. Thread pool

package pool;

import java.util.concurrent.*;

/**
 * @Author: lwen
 * @Date: Created in 2017/8/19 17:56
 * @Description:
 */

class Test implements Runnable{

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName());
    }
}


class Test1 implements Callable<Integer>{

    @Override
    public Integer call() throws Exception {
        int sum=0;
        for (int i = 0; i <= 100; i++) {
            sum+=i;
        }
        return sum;
    }
}
public class Main {
    public static void main(String[] args) throws ExecutionException,InterruptedException {

        //注意线程池里面装的都是线程,这些线程到时候再次使用的时候不需要再次创建,也就是代表操作系统不需要再次分配资源,分配pid等等
        //而不是说里面装的是任务,这里仅仅就是线程而已
        ExecutorService executor= Executors.newFixedThreadPool(10);  //固定大小的线程池
        ExecutorService executor1=Executors.newSingleThreadExecutor(); //一个线程的线程池
        ExecutorService executor2=Executors.newCachedThreadPool(); //动态变化的线程池
        for (int i = 0; i < 20; i++) {
            executor.submit(new test());
        }

        Future<Integer> future=executor1.submit(new Test1());
        System.out.println(future.get());

        executor.shutdown(); //只有当线程池关闭的时候  程序才会停止
        executor1.shutdown();
        executor2.shutdown();
    }
}

8. Thread scheduling:

Thread scheduling can determine what operations to perform after how long.

package schedule;

import java.util.Random;
import java.util.concurrent.*;

/**
 * @Author: lwen
 * @Date: Created in 2017/8/19 18:11
 * @Description:
 */


public class Main {
    public static void main(String[] args) throws ExecutionException,InterruptedException {
        scheduledexecutorservice service= Executors.newScheduledThreadPool(5);
        for (int i = 0; i < 5; i++) {
            Future<Integer> future=service.schedule(new Callable<Integer>() {
                @Override
                public Integer call() throws Exception {
                    int random=new Random().nextInt(100);
                    System.out.println(Thread.currentThread().getName()+":"+random);
                    return random;
                }
            },1,TimeUnit.SECONDS);
            System.out.println(future.get());
        }
        service.shutdown();
    }
}
The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>