多线程与并发库

Posted wust_ouyangli

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了多线程与并发库相关的知识,希望对你有一定的参考价值。

同步方式

技术分享图片
import javax.xml.stream.events.StartDocument;

public class TestSynchronized {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        TestSynchronized test = new TestSynchronized();
        test.init();
    }
    
    void init() {
        final Outputer outputer = new Outputer();
        
        new Thread(new Runnable(){
            @Override
            public void run() {
                // TODO Auto-generated method stub
                while(true){
                    try {
                        Thread.sleep(10);
                    } catch (Exception e) {
                        // TODO: handle exception
                        e.printStackTrace();
                    }
                    outputer.Output("wangyuyuyuyuyuyuyuyu");
                }
                
            }
        }){
        }.start();
        
        new Thread(new Runnable() {
            
            @Override
            public void run() {
                // TODO Auto-generated method stub
                while(true){
                    try {
                        Thread.sleep(10);
                    } catch (Exception e) {
                        // TODO: handle exception
                        e.printStackTrace();
                    }
                    outputer.Output("zhouzhanzhaozhaozhaozhao");
                }
            }
        }){
        }.start();
    }
    
    
    class Outputer{
        final static String lockKey = "lock";
        //定义输出函数
        //第一种方式,提供某个锁
        public void Output(String name){
            int len = name.length();
            synchronized (lockKey) {
                for (int i = 0; i < len; i++){
                    System.out.print(name.charAt(i));
                }
                System.out.println();
            }
        }
        //第二种方式,锁住自己
        public void Output1(String name){
            int len = name.length();
            synchronized (this) { //也可以用Outputer.class
                for (int i = 0; i < len; i++){
                    System.out.print(name.charAt(i));
                }
                System.out.println();
            }
        }
        //第三种方式,函数前面加关键字synchronized
        public synchronized void Output2(String name){
            int len = name.length();
            for (int i = 0; i < len; i++){
                System.out.print(name.charAt(i));
            }
            System.out.println();
                
            
        }
    }

}
View Code

定时器Timer

技术分享图片
import java.util.Timer;
import java.util.TimerTask;

public class TimerTest {
    public static void main(String[] args){
        new Timer().schedule(new TimerTask(){

            @Override
            public void run() {
                // TODO Auto-generated method stub
                System.out.println("boom");
            }
            
        }, 3000);
    }
}
View Code

HashMap存储线程

技术分享图片
import java.util.HashMap;
import java.util.Map;
import java.util.Random;

public class TestThreadMap {
    private static HashMap<Thread, Integer> map = new HashMap<Thread, Integer>();
    public static void main(String[] args) {
        //TestThreadMap testThreadMap = new TestThreadMap();
        for (int i = 0; i < 2; i++) {
            new Thread(new Runnable() {
                
                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    int data = new Random().nextInt();
                    map.put(Thread.currentThread(), data);
                    new A().Get();
                    new B().Get();
                }
            }){}.start();
             
            
        }
    }
    static class A{
        public void Get(){
            int data = map.get(Thread.currentThread());
            System.out.println("A from " + Thread.currentThread().getName() + " get data " + data);
        }
    }
    
    static class B{
        public void Get(){
            int data = map.get(Thread.currentThread());
            System.out.println("B from " + Thread.currentThread().getName() + " get data " + data);
        }
    }
}
View Code

ThreadLocal类似HashMap存储线程

技术分享图片
import java.util.HashMap;
import java.util.Map;
import java.util.Random;

public class TestThreadMap {
    private static HashMap<Thread, Integer> map = new HashMap<Thread, Integer>();
    public static void main(String[] args) {
        //TestThreadMap testThreadMap = new TestThreadMap();
        for (int i = 0; i < 2; i++) {
            new Thread(new Runnable() {
                
                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    int data = new Random().nextInt();
                    map.put(Thread.currentThread(), data);
                    new A().Get();
                    new B().Get();
                }
            }){}.start();
             
            
        }
    }
    static class A{
        public void Get(){
            int data = map.get(Thread.currentThread());
            System.out.println("A from " + Thread.currentThread().getName() + " get data " + data);
        }
    }
    
    static class B{
        public void Get(){
            int data = map.get(Thread.currentThread());
            System.out.println("B from " + Thread.currentThread().getName() + " get data " + data);
        }
    }
}
View Code
技术分享图片
import java.util.Random;


public class TestThreadlocal_2 {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        for (int i = 0; i < 2; i++){
            new Thread(new Runnable() {
                
                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    int data = new Random().nextInt();
                    MyData.getInstance().setName("myData" + data);
                    MyData.getInstance().setAge(data);
                    new A().Get();
                    new B().Get();
                }
            }){}.start();
        }

    }
    
    static class A{
        public void Get(){
            MyData data = MyData.getInstance();
            System.out.println("A from " + Thread.currentThread().getName() + " get data " + data.getName() + ", " + data.getAge());
        }
    }
    static class B{
        public void Get(){
            MyData data = MyData.getInstance();
            System.out.println("B from " + Thread.currentThread().getName() + " get data " + data.getName() + ", " + data.getAge());
        }
    }

}

class MyData{
    String name;
    int age;
    
    public static /*synchronized*/ MyData getInstance(){
        MyData instance = threadLocal.get();
        if (instance == null){  //不存在就创建一个与本线程有关的实例对象
            instance = new MyData();
            threadLocal.set(instance);
            
        }
        return instance;
    }
    
    //private static MyData instance = null;
    private static ThreadLocal<MyData> threadLocal = new ThreadLocal<MyData>();
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    
}
View Code

线程池

技术分享图片
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class TestThreadPool {
    public static void main(String[] args){
        //固定大小的线程池
        ExecutorService threadPool = Executors.newFixedThreadPool(3);
        //缓存线程池,当线程不够用时会自动增加,多了会自动减少
        //ExecutorService threadPool = Executors.newCachedThreadPool();
        //单一线程池,线程死了可以重新启动
        //ExecutorService threadPool = Executors.newSingleThreadExecutor();
        for (int i = 1; i <= 10; i++){
            final int taskid = i;
            threadPool.execute(new Runnable() {
                
                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    for (int j = 1; j <= 10; j++) {
                        System.out.println(Thread.currentThread().getName() + " is loop of " + j + " for task of " + taskid);
                    }
                }
            });
        }
        System.out.println("all have finished");
        threadPool.shutdown(); //线程池里没有任务了,线程池才关闭,等10个任务都完成后才关闭
        //threadPool.shutdownNow(); //一个线程完成之后立马关闭,此时只完成了3个任务
        
        /*//定时器线程池
        Executors.newScheduledThreadPool(3).schedule(
                new Runnable() {
                    
                    @Override
                    public void run() {
                        // TODO Auto-generated method stub
                        System.out.println("booming");
                    }
                }, 
                6,
                TimeUnit.SECONDS); //多长时间后执行任务
*/        
        Executors.newScheduledThreadPool(3).scheduleAtFixedRate( //以固定频率执行任务
                new Runnable() {
                    
                    @Override
                    public void run() {
                        // TODO Auto-generated method stub
                        System.out.println("booming");
                    }
                }, 
                6,  //初始时间
                2,  //间隔时间
                TimeUnit.SECONDS);
        
        
    }
}
View Code

锁Lock

技术分享图片
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import javax.xml.stream.events.StartDocument;

public class TestLock {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        TestLock test = new TestLock();
        test.init();
    }
    
    void init() {
        final Outputer outputer = new Outputer();
        
        new Thread(new Runnable(){
            @Override
            public void run() {
                // TODO Auto-generated method stub
                while(true){
                    try {
                        Thread.sleep(10);
                    } catch (Exception e) {
                        // TODO: handle exception
                        e.printStackTrace();
                    }
                    outputer.Output("wangyuyuyuyuyuyuyuyu");
                }
                
            }
        }){
        }.start();
        
        new Thread(new Runnable() {
            
            @Override
            public void run() {
                // TODO Auto-generated method stub
                while(true){
                    try {
                        Thread.sleep(10);
                    } catch (Exception e) {
                        // TODO: handle exception
                        e.printStackTrace();
                    }
                    outputer.Output("zhouzhanzhaozhaozhaozhao");
                }
            }
        }){
        }.start();
    }
    
    
    class Outputer{
        Lock lock = new ReentrantLock(); //
        public void Output(String name){
            int len = name.length();
            
            lock.lock();
            try {
                
                for (int i = 0; i < len; i++){
                    
                    System.out.print(name.charAt(i));
                }
                System.out.println("");
            } finally{
                // TODO: handle exception
                lock.unlock();

            }
        }
        
    }

}
View Code

读写锁ReadWriterLock

技术分享图片
import java.util.HashMap;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class TestReadWriterLock {
    HashMap<String, Object> mp = new HashMap<String, Object>();
    private ReadWriteLock rwl = new ReentrantReadWriteLock();
    public Object Get(String key){
        rwl.readLock().lock();
        Object value = null;
        try {
            value = mp.get(key);
            if (value == null) {
                rwl.readLock().unlock();
                rwl.writeLock().lock();
                try {
                    if (value == null){
                        value = "aaa";
                    }
                    
                } finally {
                    // TODO: handle finally clause
                    rwl.writeLock().unlock();
                }
                rwl.readLock().lock();
            }
        } finally {
            rwl.readLock().unlock();
        }
        return value;
    }
}
View Code

信号灯Semaphere(控制当前运行的线程个数)

技术分享图片
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import java.util.function.IntToDoubleFunction;

public class TestSemaphere {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        /*1.创建线程池
         *2.创建信号灯,大小为3 
         *3.循环10次,Runnable里设置信号灯acqure
         */
        
        ExecutorService es = Executors.newCachedThreadPool();
        Semaphore semaphore = new Semaphore(3);
        for(int i = 0; i < 10; i++){
            es.execute(new Runnable() {
                
                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    try {
                        semaphore.acquire();
                    } catch (Exception e) {
                        // TODO: handle exception
                        e.printStackTrace();
                    }
                    
                    System.out.println("线程" + Thread.currentThread().getName() + "进入");
                    try {
                        Thread.sleep((int)Math.random() * 10000);
                    } catch (Exception e) {
                        // TODO: handle exception
                        e.printStackTrace();
                    }
                    System.out.println("线程" + Thread.currentThread().getName() + "即将结束");
                    semaphore.release();
                    System.out.println("线程" + Thread.currentThread().getName() + "已结束");
                    es.shutdown();
                    
                }
            });
        }
    }

}
View Code

数据交换Exchanger(当两个数据都到达后才能进行交换,否则阻塞)

技术分享图片
import java.util.concurrent.Exchanger;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class TestExchanger {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        ExecutorService es = Executors.newCachedThreadPool();
        Exchanger<String> exchanger = new Exchanger<String>();
        es.execute(new Runnable() {
            
            @Override
            public void run() {
                // TODO Auto-generated method stub
                try {
                    String data1 = "x";
                    System.out.println("线程" + Thread.currentThread().getName() + "正在把数据" + data1 + "发送出去");
                    Thread.sleep((int)(Math.random() * 5000));
                    String getData = exchanger.exchange(data1);
                    System.out.println("线程" + Thread.currentThread().getName() + "接受到的数据为: " + getData);
                } catch (Exception e) {
                    // TODO: handle exception
                    e.printStackTrace();
                }
            }
        });
        
        es.execute(new Runnable() {
            
            @Override
            public void run() {
                // TODO Auto-generated method stub
                try {
                    String data1 = "y";
                    System.out.println("线程" + Thread.currentThread().getName() + "正在把数据" + data1 + "发送出去");
                    Thread.sleep((int)(Math.random() * 5000));
                    String getData = exchanger.exchange(data1);
                    System.out.println("线程" + Thread.currentThread().getName() + "接受到的数据为: " + getData);
                } catch (Exception e) {
                    // TODO: handle exception
                    e.printStackTrace();
                }
            }
        });
    }

}
View Code

同步屏障CyclicBarrier(多个线程彼此等待,集合后再往后运行)

技术分享图片
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class TestCyclicBarrier {
    //多个线程彼此等待,集合后再运行
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        //创建线程池和CyclicBarrier,同时运行多个线程,调用await
        
        ExecutorService es = Executors.newCachedThreadPool();
        final CyclicBarrier cb = new CyclicBarrier(3);
        for (int i = 0; i < 3; i++){
            es.execute(new Runnable() {
                
                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    try {
                        Thread.sleep((int)(Math.random() * 1000));
                        System.out.println("线程" + Thread.currentThread().getName() + "到达集合点1");
                        System.out.println("当前有" + (cb.getNumberWaiting()+1) + "人在等待");
                        cb.await();
                        Thread.sleep((int)(Math.random() * 1000));
                        System.out.println("线程" + Thread.currentThread().getName() + "到达集合点2");
                        System.out.println("当前有" + (cb.getNumberWaiting()+1) + "人在等待");
                        cb.await();
                        Thread.sleep((int)(Math.random() * 1000));
                        System.out.println("线程" + Thread.currentThread().getName() + "到达集合点3");
                        System.out.println("当前有" + (cb.getNumberWaiting()+1) + "人在等待");
                        cb.await();
                        
                    } catch (Exception e) {
                        // TODO: handle exception
                        e.printStackTrace();
                    }
                    
                }
            });
        }
        es.shutdown();

    }

}
View Code

CountDownLatch(类似倒计时计数器,当计数减为0时,所有等待者才开始执行)

技术分享图片
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class TestCountDownLatch {
    //类似倒计时计数器,当计数减为0的时候,所有等待者才开始执行
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        //创建两个计数器,一个为1,一个为3,代表一个裁判员,三个运动员,裁判员在未下达命令前运动员等待,下达命令后才执行
        //等三个运动员都到达终点后,裁判员才公布成绩
        ExecutorService es = Executors.newCachedThreadPool();
        CountDownLatch cdOrder = new CountDownLatch(1);
        CountDownLatch cdAnswer = new CountDownLatch(3);
        for (int i = 0; i < 3; i++) {
            final int id = i;
            es.execute(new Runnable() {
                
                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    try {
                        System.out.println("运动员" + id + "正准备接受命令");
                        cdOrder.await();
                        System.out.println("运动员"+ id + "接受到命令");
                        Thread.sleep((int)(Math.random() * 5000));
                        System.out.println("运动员" + id + "到达终点");
                        cdAnswer.countDown();
                        
                    } catch (Exception e) {
                        // TODO: handle exception
                        e.printStackTrace();
                    }
                    
                    
                }
            });
        }
        
        try {
            Thread.sleep(1000);
            System.out.println("裁判员发出指令");
            cdOrder.countDown();
            System.out.println("裁判员等待所有运动员到达终点");
            cdAnswer.await();
            System.out.println("裁判员公布成绩");
        } catch (Exception e) {
            // TODO: handle exception
        }
    }

}
View Code

Callable和Future

技术分享图片
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class TestCallableAndFuture {
    public static void main(String[] args) throws InterruptedException, ExecutionException, TimeoutException{
        ExecutorService threadPool = Executors.newSingleThreadExecutor();
        Future future =
                threadPool.submit(new Callable<String>() {
                    @Override
                    public String call() throws Exception {
                        // TODO Auto-generated method stub
                        Thread.sleep(2000);
                        return "hello";
                    }
                });
        
        System.out.println("得到结果: " + future.get()); //callable完成任务返回结果,由future去拿,需要等待一段时间
        //System.out.println("得到结果: " + future.get(1, TimeUnit.SECONDS)); //要在规定的时间内得到结果,如果得不到就抛出异常
        
        //CompletionService 用于提交一组callable任务,并用take方法得到一个已完成任务的future对象
        ExecutorService threadPool2 = Executors.newFixedThreadPool(10);
        CompletionService<Integer> completionService = new ExecutorCompletionService<Integer>(threadPool2);
        
        for (int i = 1; i <= 10; i++){
            final int taskid = i;
        completionService.submit(new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                // TODO Auto-generated method stub
                try {
                    Thread.sleep(new Random().nextInt(5000));
                } catch (Exception e) {
                    // TODO: handle exception
                }
                return taskid;
            }
        });
        }
        
        for (int i = 1; i <= 10; i++){
            System.out.println(completionService.take().get());
        }
    }

}
View Code

阻塞队列ArrayBlockingQueue

技术分享图片
import java.util.concurrent.ArrayBlockingQueue;

public class TestArrayBlockingQueue {
    //阻塞队列当队列为空时take会阻塞,当队列满时put会阻塞
    //用两个阻塞队列模拟两个线程交替运行
    //两个阻塞队列大小均设置为1,其中一个放一个数据
    
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Business business = new Business();
        new Thread(new Runnable() {
            
            @Override
            public void run() {
                // TODO Auto-generated method stub
                for (int j = 1; j <= 10; j++) {
                    business.Sub(j);
                }
            }
        }){}.start();
        
        for (int j = 1; j <= 10; j++) {
            business.Main(j);
        }
        
    }
    
    static class Business{
        ArrayBlockingQueue abq1 = new ArrayBlockingQueue(1);
        ArrayBlockingQueue abq2 = new ArrayBlockingQueue(1);
        public Business() 
        {
            try {
                abq2.put(1);
            } catch (Exception e) {
                // TODO: handle exception
                e.printStackTrace();
            }
        }
        public void Sub(int j){
            try {
                abq1.put(1);
                for (int i = 1; i <= 10; i++){
                    System.out.println("sub thread " + i + " of loop " + j);
                }
                abq2.take();
            } catch (Exception e) {
                // TODO: handle exception
                e.printStackTrace();
            }
            
        }
        
        public void Main(int j){
            try {
                abq2.put(1);
                for (int i = 1; i <= 10; i++){
                    System.out.println("main thread " + i + " of loop " + j);
                }
                abq1.take();
            } catch (Exception e) {
                // TODO: handle exception
                e.printStackTrace();
            }
        }
    }

}
View Code

练习: 子线程运行10次,主线程运行20次,交替运行

技术分享图片
public class prictice_1 {
    //子线程运行10次,主线程运行20次
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Business business = new Business();
        new Thread(new Runnable() {
            
            @Override
            public void run() {
                // TODO Auto-generated method stub
                for (int j = 1; j <= 10; j++) {
                    business.Sub(j);
                }
            }
        }){}.start();
        
        for (int j = 1; j <= 10; j++) {
            business.Main(j);
        }
    }
    

}
class Business{
    private boolean isSub = true;
    public synchronized void Sub(int j){
        while (!isSub) {
            try {
                this.wait();
            } catch (Exception e) {
                // TODO: handle exception
                e.printStackTrace();
            }
        }
        for (int i = 1; i <= 10; i++){
            System.out.println("sub thread " + i + " of loop " + j);
        }
        isSub = false;
        this.notify();
    }
    
    public synchronized void Main(int j){
        while (isSub){
            try {
                this.wait();
            } catch (Exception e) {
                // TODO: handle exception
                e.printStackTrace();
            }
        }
        for (int i = 1; i <= 20; i++){
            System.out.println("main thread " + i + " of loop " + j);
        }
        isSub = true;
        this.notify();
    }
}
View Code

 

以上是关于多线程与并发库的主要内容,如果未能解决你的问题,请参考以下文章

Java多线程与并发库高级应用

Java多线程与并发库4.传统线程同步通信技术

Java复习——多线程与并发库

Java多线程与并发库7.多个线程之间共享数据的方式探讨

Java多线程与并发库4.传统线程同步通信技术

(黑马Java多线程与并发库高级应用)05 线程范围内共享变量的概念与作用