死锁问题和线程池

本文探讨了Java多线程中可能出现的死锁问题及其解决方案,通过生产者消费者模式来避免线程间的互相等待。同时,介绍了Java线程池的概念,使用Executors创建线程池,并展示了如何提交任务到线程池执行。线程池的优化方面,提到了ThreadPoolExecutor的构造参数和其重要性。此外,还讨论了Java同步机制如`synchronized`和`volatile`关键字的作用。
摘要由CSDN通过智能技术生成

1.死锁问题

1.1死锁

1.多线程出现安全问题可以使用同步方法或者同步代码块以及Lock解决安全问题,但是有可能出现死锁
2.死锁:当前多个线程操作不是同一个子类对象,可能会造成线程互相等待情况
    解决方法:使用生产者和消费者模式

1.2 生产者消费者模式思路以及实现代码

1.SetThread类-->生产者所在线程资源类
  GetThread-->消费者所在线程资源类
  Student-->生产者线程不断产生学生数据,消费者线程不断使用学生数据
  StudentTest-->主线程
2.
    public class Student{
        private String name;
        private int age;
        private boolean flag;
        
        public synchronized void set(String name,int age){//同步方法锁对象:this
            if(this.flag){//flag是否为false
                try{
                    this.wait();//立即释放锁
                }catch(InterruptedException e){
                    e.printStackTrace();
                }
            }
            //产生数据
            this.name = name;
            this.age = age;
            //修改flag的值
            this.flag = true;
            //唤醒对方线程
            this.notify();
        }
        public synchronized void get(){
            if(!this.flag){
                try{
                    this.wait();
                }catch(InterruptedException e){
                    e.printStackTrace();
                }
            }
            sout(this.name);
            sout(this.age);
            
            this.flag = false;
            this.notify();   
        }  
    }
public class SetThread implements Runnable{
    private Student s;
    
    public SetThread(Student s){//构造方法,传参为Student类
        this.s = s;
    }
    
    int x = 0;
    public void run(){
        while(true){
        if(x % 2 == 0){
            s.set("高圆圆",42);
        }else{
            s.set("赵又廷",45);
        }
        x++;
    	}
	}
}
public class GetThread implements Runnable{
    private Student s;
    public GetThread(Student s){
        this.s = s;
    }
    public void run(){
        while(true){
            s.get();
        }
    }
}
public class StudentTest{
    public static void main(String[] args){
        Student s = new Student();
        
         //创建生成资源类对象
        SetThread st = new SetThread(s) ;
         //创建消费者资源类对象
        GetThread gt = new GetThread(s) ;

        //创建线程类对象
        Thread t1 = new Thread(st) ;
        Thread t2 = new Thread(gt) ;

        //分别启动线程
        t1.start() ;
        t2.start() ;
        
    }
}

2.线程池

1.线程池:创建一个固定的可重用的线程的数量
2.(1)JDK提供了一个工厂类:Executors
		静态方法:public static ExecutorService newFixedThreadPool(int nThreads):建一个线程池,该线程池重用固定数量的线程
  (2)JDK提供了一个接口:ExecutorService:线程池
            <T> Future<T> submit(Callable<T> task):提供异步任务计算的结果
            Future是接口,异步任务计算的结果
  (3)void shutdown():启动有序关闭
  (4)V get():获取计算结果

2.1创建线程池代码实现

1.
    public class MyCallable implements Callable<>{
    public Object call() throws Execption{
        for(int i=0;i<100;i++){
            sout(Thread.currentThread().getName()+":"+i);
        }
        return null;
    }
}
	public class Demo{
    public static void main(String[] args){
        ExecutorService threadPoll = Executors.newFixedThreadPool(2);//创建两个固定线程
        threadPoll.submit(new MyCallable());//提交一个线程操作
        threadPoll.submit(new MyCallable());//提交一个线程操作
        
        threadPoll.shutdown();//关闭线程池        
    }
}
2.
    需求:
       使用线程池创建两个线程,然后分别计算求和
           一个线程:1-100之间的和
           另一个线程:1-200之间的和
   public class MyCallable implements Callable<Integer>{
       private Integer num;
       public MyCallable(Integer num){
           this.num = num;
       }
       public Integer call() throws Execption{
            int sum = 0;
       		for(int x = 1 ; x <=num ; x++){
            sum += x ;
        } 
        return sum;
       }
   }
	public class Demo{
        public static void main(String[] args) throws 
            ExecutionException, InterruptedException{
            ExecutionService threadPool = Executors.newFixedThreadPoll(2);
            
            Future<Integer> f1 = threadPool.submit(new MyCallable(100));
            Future<Integer> f2 = threadPool.submit(new MyCallable(200));
            
            Integer i1 = f1.get();
            Integer i2 = f2.get();
            
            sout(i1);
            sout(i2);
            
            threadPool.shutdown();
        }
    }

2.2 面试题

1.线程池的优化
  线程池的参数
    public static ExecutorService newFixedThreadPoll(int nThreads){
    	//ThreadPoolExecuto是ExecutorService的子实现类
    	return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());)
	}
2.ThreadPoolExecutor的构造方法之一:
	 public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler)
3.成员变量:
	private final ReentrantLock mainLock = new ReentrantLock();//使用锁对象
	private volatile int corePoolSize;//核心线程数量
	private volatile int maximumPoolSize;//最大线程数量 ,当前创建的线程池的数量固定,然后有新的线程进来,如果超过最大线程数量,等待一定时间,看下一个参数
	private volatile RejectedExecutiongHandler handler;//拒绝策略
	private volatile long keepAliveTime;//创建一个新的线程对象的时候,激活的时间,如果超过这个时间,那么就进不了这个线程,原因是超过了最大的线程池的线程数
	private volatile ThreadFactory threadFactoy;//具体就是创建线程对象 new Thread()
	private final BlockingQueue<Runnable> workQueue;//工作队列-->继承Queue extends Collection<E>集合

2.3 java的同步机制

synchronized同步代码块/同步方法
变量上面加入volatile
等待唤醒机制wait()notify()
都可解决线程安全问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值