• 线程学习补充


    解决线程安全问题:
    
    1.synchronized隐式锁
        同步代码块
        同步方法
    2.JDK1.5后
        同步锁Lock   lock()方方法上锁  必须要,unlock 方法解锁
        private Lock lock=new ReentranLock();
        public void run(){
            while(true){
                lock.lock();//上锁
                try{
                    if(tick>0){
                        try{
                            Thread.sleep(200);
                        }catch(InterruptedException e){
                        }
                        sysytem.out.println(Thread.currentThread().getName());
                    }                
                }finally{
                    lock.unlock();//释放锁
                }
            }    
        }
        
    1,线程交替打印 lock示例:condition控制线程通信
    public class TestABCAlternate{
        public static void main(String[] args){
            AlternateDemo ad=new AlternateDemo();
            new Thread(new Runnable(){
                public void run(){
                    for(int i=1;i<=20;i++){
                        ad.loopA(i);
                    }
                }
            },"A").start();
            new Thread(new Runnable(){
                public void run(){
                    for(int i=1;i<=20;i++){
                        ad.loopB(i);
                    }
                }
            },"B").start();
            new Thread(new Runnable(){
                public void run(){
                    for(int i=1;i<=20;i++){
                        ad.loopC(i);
                    }
                }
            },"C").start();
        }
    }
    class AlternateDemo{
        private int number=1;//当前正在执行线程的标记
        private Lock lock=new ReentranLock();
        private Condition condition1=lock.newCondition();
        private Condition condition2=lock.newCondition();
        private Condition condition3=lock.newCondition();    
        public void loopA(){
            lock.lock();
            try{
                if(number!=1){
                    condition1.await();//等待,,说明不属于1 打印
                }
                for(int i=1;i<=1;i++){
                    system.out.println(Thread.currentThread().getName()+ i +totalLoop);
                }
                number=2;
                condition2.signal();//唤醒2        
            }catch(Exception e){
            
            }finally{
                lock.unlock();
            }    
        }
        public void loopB(){
            lock.lock();
            try{
                if(number!=1){
                    condition1.await();//等待,,说明不属于1 打印
                }
                for(int i=1;i<=1;i++){
                    system.out.println(Thread.currentThread().getName()+ i +totalLoop);
                }
                number=3;
                condition3.signal();//唤醒2       
            }catch(Exception e){    
            }finally{
                lock.unlock();
            }    
        }
        public void loopC(){
            lock.lock();
            try{
                if(number!=1){
                    condition1.await();//等待,,说明不属于1 打印
                }
                for(int i=1;i<=1;i++){
                    system.out.println(Thread.currentThread().getName()+ i +totalLoop);
                }
                number=1;
                condition1.signal();//唤醒2        
            }catch(Exception e){        
            }finally{
                lock.unlock();
            }    
        }    
    }
        
    读写锁:ReadWriteLock  写写/读写  需要互斥
        读可以允许多个线程操作
        写只能有一个线程操作
    class ReadWriteLockDemo{
        private int number=0;
        private ReadWriteLock lock=new ReentranReadWriteLock();//创建读写锁
        
        //读
        public void get(){
            lock.readLock.lock();//上锁
            try{
                system.out.println(number);
            }finally{
                lock.readLock.unlock();//释放锁
            }
        }    
        //写
        public void set(int number){
            lock.writeLock.lock();
            try{
                system.out.println(number);
            }finally{
                lock.writeLock.unlock();//释放锁
            }
        }    
    }    
        
    1.两个普通同步方法,两个线程,标准打印?one  two
    2.新增Thread.sleep()给getOne(),打印? one  two 
    3.新增普通同步方法getThread(),打印? one two
    4.两个普通同步方法,两个number对象,打印?two  one 
    5.修改getOne()为静态同步方法,一个number对象?two one
    6.修改两个方法均为静态同步方法,一个number对象?one  two
    7.一个静态同步方法,一个非静态同步方法,两个number对象?two  one 
    8.两个静态同步方法,两个number对象?one  two
    
    线程八锁的关键:
    1.非静态方法的锁默认为this,静态方法的锁为对应的class实例
    2.某一个时刻内,只能有一个线程持有锁,无论几个方法。
        
        
    一、线程池:
        提供了一个线程队列,队列中保存着所有等待状态的线程,
        避免了创建与销毁开销,提高了响应速度。
    二、线程池的体系结构
        java.util.concurrent.Executor:负责线程的使用与调度的根接口
            ExecutorService子接口:线程池的主要接口
                ThreadPoolExecutor 线程池的实现类
                ScheduledExecutorService 子接口:负责线程的调度
                    ScheduledThreadPollExecutor:继承ThreadPoolExecutor,实现ScheduledExecutorService
    三、工具类 Executors
            ExecutorService  newFixedThreadPool();创建固定大小的线程池
            ExecutorService  newCachedThreadPool();缓存线程池,线程池的数量不固定,可以根据需求自动的更改数量
            ExecutorService  newSingleThreadExecutor();创建单个线程池,线程池中只有一个线程
         
         ScheduledExecutorService  newScheduledThreadPool();创建固定大小的线程,可以延迟或定时的执行任务。
    public class TestThreadPool{
        public static void main(String[] args){
            //1.创建线程池  固定大小线程池
            ExecutorService pool=Executors.newFixedThreadPool(5);
            ThreadPoolDemo ted=new ThreadPoolDemo();
            //2.为线程池中的线程分配任务
            pool.submit(ted);
            //3.关闭线程池
            pool.shutdown();
            
        }
    
        class ThreadPoolDemo implements Runnable{
            private int i=0;
            public void run(){
                while(i<100){
                    i++;
                    system.out.println("");
                }
            }    
        }
        
        Callable位于java.util.concurrent包下,它也是一个接口,在它里面也只声明了一个方法,只不过这个方法叫做call()
        Future就是对于具体的Runnable或者Callable任务的执行结果进行取消、查询是否完成、获取结果。
        必要时可以通过get方法获取执行结果,该方法会阻塞直到任务返回结果
        
        
        创建执行线程的方式三:
            1.实现Callable接口,相较于实现Runnable接口的方式,方式可以有返回值,并且可以抛出异常。
            2.执行callable方式,需要FutureTask实现类的支持,用于接收运算结果,FutureTask是Future接口的实现类
        class SumTask implements Callable<Long> {
    
            @Override
            public Long call() throws Exception {
    
                long sum = 0;
                for (int i = 0; i < 9000; i++) {
                    sum += i;
                }
                return sum;
            }
    
            public static void main(String[] args) throws ExecutionException, InterruptedException {
                System.out.println("Start:" + System.nanoTime());
                // 将Callable写的任务封装到一个由执行者调度的FutureTask对象
                FutureTask<Long> futureTask = new FutureTask<Long>(new SumTask());
                // 创建线程池并返回ExecutorService实例 
                Executor executor=Executors.newSingleThreadExecutor();
                //执行任务
                executor.execute(futureTask);
                //打印输出返回值
                System.out.println(futureTask.get());
                System.out.println("End:" + System.nanoTime());
        }
    
    } 
    注意点:

    避免使用Executors创建线程池,主要是避免使用其中的默认实现,那么我们可以自己直接调用ThreadPoolExecutor的构造函数来自己创建线程池。
    在创建的同时,给BlockQueue指定容量就可以了。
    private static ExecutorService executor = new ThreadPoolExecutor(10, 10,
    60L, TimeUnit.SECONDS,
    new ArrayBlockingQueue(10));
    这种情况下,一旦提交的线程数超过当前可用线程数时,就会抛出java.util.concurrent.RejectedExecutionException,
    这是因为当前线程池使用的队列是有边界队列,队列已经满了便无法继续处理新的请求。
    但是异常(Exception)总比发生错误(Error)要好

    ThreadPoolExecutor(int corePoolSize,
    int maximumPoolSize,
    long keepAliveTime,
    TimeUnit unit,
    BlockingQueue workQueue,
    ThreadFactory threadFactory,
    RejectedExecutionHandler handler)







  • 相关阅读:
    eureka的fetch-registry属性解释
    数据结构设计
    typescript let和const区别
    JDK8新特性
    Synchronized的内存可见性
    java实现打印功能
    idea单元测试jpa注入失败问题----来自Spring Cloud微服务实战-idea版的 廖师兄的product
    eclipse快速生成接口
    读取 Excel 之 Epplus
    [转][Dapper]参数化查询慢
  • 原文地址:https://www.cnblogs.com/qiuxiaoliang/p/9868897.html
Copyright © 2020-2023  润新知