多线程并发库(一)

来源:互联网 发布:c语言点滴 epub 编辑:程序博客网 时间:2024/05/01 11:21

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==生成的数据是:-229198565Thread-2==生成的数据是:-1892334218Thread-0==生成的数据是:-1126013147Thread-0A:取出的数据是:-1126013147Thread-1A:取出的数据是:-229198565Thread-2A:取出的数据是:-1892334218Thread-1B:取出的数据是:-229198565Thread-2B:取出的数据是:-1892334218Thread-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;}@Overridepublic String toString() {    return "Student [name=" + name + ", age=" + age + "]";}}

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

======显示次数==============显示次数==============显示次数========Thread-0==生成的数据是:81Thread-1==生成的数据是:67Thread-2==生成的数据是:81Thread-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();        }    }}
1 0
原创粉丝点击