多线程并发库(一)

ThreadLocal

是线程局部变量。在多线程中,实现每个线程中变量的私有性。

例子一

在该例子中,在同一个线程中通过调用类A和类B的getData()方法获取的数据是一致的。

public class ThreadLocalTest {
static ThreadLocal<Integer> threadLocal = new ThreadLocal<>();
public static void main(String[] args) {
    final ThreadLocalTest tlt = new ThreadLocalTest();
    for(int i=0;i<3;i++){
        new Thread(new Runnable() {
            @Override
            public void run() {
                int data = new Random().nextInt();
                threadLocal.set(data);
                System.out.println(Thread.currentThread().getName()+"==生成的数据是:"+data);
                tlt.new A().getData();
                tlt.new B().getData();
            }
        }).start();
    }
}
class A{
    public void getData(){
        System.out.println(Thread.currentThread().getName()+"A:"+"取出的数据是:"+threadLocal.get());
    }
}
class B{
    public void getData(){
        System.out.println(Thread.currentThread().getName()+"B:"+"取出的数据是:"+threadLocal.get());
    }
}

** }
结果:**

Thread-1==生成的数据是:-229198565
Thread-2==生成的数据是:-1892334218
Thread-0==生成的数据是:-1126013147
Thread-0A:取出的数据是:-1126013147
Thread-1A:取出的数据是:-229198565
Thread-2A:取出的数据是:-1892334218
Thread-1B:取出的数据是:-229198565
Thread-2B:取出的数据是:-1892334218
Thread-0B:取出的数据是:-1126013147

例子二

实现每个线程只拥有一个实例对象的写法。

public class ThreadLocalForObjTest {
static ThreadLocal<Student> threadLocal = new ThreadLocal<>();
public static void main(String[] args) {
    final ThreadLocalForObjTest tlt = new ThreadLocalForObjTest();
    for(int i=0;i<3;i++){
        new Thread(new Runnable() {
            @Override
            public void run() {
                int data = new Random().nextInt(150);
                Student s = Student.getInstance();
                s.setAge(data);
                s.setName("lzl"+data);
                threadLocal.set(s);
                System.out.println(Thread.currentThread().getName()+"==生成的数据是:"+data);
                tlt.new A().getData();
                tlt.new B().getData();
            }
        }).start();
    }
}
class A{
    public void getData(){
        System.out.println(Thread.currentThread().getName()+"A:"+"取出的数据是:"+threadLocal.get().toString());
    }
}
class B{
    public void getData(){
        System.out.println(Thread.currentThread().getName()+"B:"+"取出的数据是:"+threadLocal.get().toString());
    }
}
}
class Student{
private String name;
private int age;
private static ThreadLocal<Student> map = new ThreadLocal<Student>();
public static Student getInstance(){
    Student instance = map.get();
    if(instance ==null){
        instance = new Student();
        map.set(instance);
        System.out.println("======显示次数========");
    }
    return instance;
}
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;
}
@Override
public String toString() {
    return "Student [name=" + name + ", age=" + age + "]";
}
}

结果
三个线程,创建了三个实例对象。并且保证单个线程中的数据是私有的。

======显示次数========
======显示次数========
======显示次数========
Thread-0==生成的数据是:81
Thread-1==生成的数据是:67
Thread-2==生成的数据是:81
Thread-2A:取出的数据是:Student [name=lzl81, age=81]
Thread-0A:取出的数据是:Student [name=lzl81, age=81]
Thread-1A:取出的数据是:Student [name=lzl67, age=67]
Thread-1B:取出的数据是:Student [name=lzl67, age=67]
Thread-0B:取出的数据是:Student [name=lzl81, age=81]
Thread-2B:取出的数据是:Student [name=lzl81, age=81]

多线程中共享数据

  1. 如果代码块执行的逻辑相同,可以在一个继承Runnable的类中实现数据的共享。
    两个线程之间共享了count数据

    public class MultiThreadShareData {
    public static void main(String[] args) {
        MyRunnable mr = new MyRunnable();
        new Thread(mr).start();
        new Thread(mr).start();
    }
    static class MyRunnable implements Runnable{
        private int count=5;
        @Override
        public void run() {
            while(true){
                System.out.println("线程名:"+Thread.currentThread().getName()+" count="+count);
                if(count<1){
                    break;
                }
                dec();
            }
    
        }
        private synchronized int dec(){
            count--;
            return count;
        }
    }
    }
    

结果:

线程名:Thread-0 count=5
线程名:Thread-1 count=5
线程名:Thread-0 count=4
线程名:Thread-1 count=3
线程名:Thread-1 count=1
线程名:Thread-0 count=2
线程名:Thread-1 count=0
  1. 如果代码块不同,就将数据封装到同一个对象中,将这个对象逐一传递给每个Runnable对象。
    两个线程之间共享了data数据

    public class MultiThreadShareData2 {
    public static void main(String[] args) {
        new MultiThreadShareData2().init();
    }
    private void init(){
        new Thread(new DecRunnable(this)).start();
        new Thread(new IncRunnable(this)).start();
    }
    int data=10;
    private synchronized void dec(){
    data--;
        System.out.println(Thread.currentThread().getName()+" data Dec="+data);
    }
    private synchronized void inc(){
        data++;
        System.out.println(Thread.currentThread().getName()+" data Inc="+data);
    }
    static class DecRunnable implements Runnable{
        private MultiThreadShareData2 data;
        public DecRunnable(MultiThreadShareData2 data2){
            this.data = data2;
        }
        @Override
        public void run() {
            while(true){
                data.dec();
            }
        }
    }
    static class IncRunnable implements Runnable{
        private MultiThreadShareData2 data;
        public IncRunnable(MultiThreadShareData2 data2){
            this.data = data2;
        }
        @Override
        public void run() {
            while(true){
                data.inc();
            }
        }
    }
    }
    

Executors的应用

  1. 创建固定大小的线程池

    ExecutorService fixedThreadPools = Executors.newFixedThreadPool(5);

  2. 创建缓存线程池

    ExecutorService threadPools = (ExecutorService) 
                Executors.newCachedThreadPool();
    
  3. 创建单一线程池(保证内存中一直有一条线程)

    ExecutorService sigleThreadPools = Executors.newSingleThreadExecutor();

  4. 线程池启动定时器

    ScheduledExecutorService threadPools = (ScheduledExecutorService) Executors.newScheduledThreadPool(3); //创建一个计时器的线程
        threadPools.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                System.out.println("hhh");
            }
        }, 2, 2, TimeUnit.SECONDS);
    }
    

    例子:

    public class ExecutorsTest {
    public static void main(String[] args) {
        ExecutorService threadPools = (ExecutorService) 
                Executors.newCachedThreadPool();//创建缓存线程池。线程的大小没有固定
        ExecutorService fixedThreadPools = Executors.newFixedThreadPool(5);//创建固定大小的线程池
        ExecutorService sigleThreadPools = Executors.newSingleThreadExecutor();//创建
        for(int i=0;i<10;i++){
            final int task = i;
            fixedThreadPools.execute(new Runnable() {
                @Override
                public void run() {
                    for(int i=0;i<10;i++){
                        System.out.println("线程名:"+Thread.currentThread().getName()+" 循环了"+i+"次,第"+task+"任务");
                    }
                }
            });
        }
        System.out.println("循环结束...");
        new ExecutorsTest().hh();
    }
    

Callable和Future

  1. 通过Executors的submit方法获取线程中返回的结果。

    public class CallableAndFuture {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        Callable<String> callable = new Callable<String>() {
            @Override
            public String call() throws Exception {
                Thread.sleep(2000);
                return "Hello Thread!";
            }
        };
        Future<String> future = executorService.submit(callable);
        System.out.println("等待结果...");
        try {
            System.out.println("结果是:"+future.get(1,TimeUnit.SECONDS)); //1s后没有拿到结果,就抛错!
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    }
    
  2. CompletionService提交多组数据

    private void futureTest2(){
        ExecutorService executorService = Executors.newFixedThreadPool(5);
        CompletionService<Integer> completionService = new ExecutorCompletionService(executorService);
        for(int i=0;i<10;i++){
            final int task=i;
            completionService.submit(new Callable<Integer>() {
                @Override
                public Integer call() throws Exception {
                    Thread.sleep(new Random().nextInt(5000));
                    return task;
                }
            });
        }
        for(int i=0;i<10;i++){
            try {
                System.out.println("结果是:"+completionService.take().get());
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
    }
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值