java死锁与线程池

一.线程的死锁

1.死锁是指两个或两个以上的进程(线程)在执行的过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞现象,若无外力作用,它们都将无法推进下去,此时称系统处于死锁状态或系统产生了死锁,这些永远都在相互等待的进程(线程)称为死锁进程(线程)

2.多个线程同时被阻塞,它们中的一个或者多个都在等待某个资源被释放,由于线程被无限期的阻塞,因此程序不可能正常终止(如:线程A持有资源1,线程B持有资源2,它们都想申请对方的资源,这两个线程就会相互等待而进入死锁状态)

举例:

   public class Ss {
        private static Object lock1=new Object();//资源1
        private static Object lock2=new Object();//资源2

        public static void main(String[] args) {
            new Thread(()->{
                synchronized (lock1){
                    System.out.println(Thread.currentThread().getName()+"获取资源1");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                    System.out.println(Thread.currentThread()+"等待获取资源2");
                    synchronized (lock2){
                        System.out.println(Thread.currentThread()+"获取资源2");
                    }
                }


            },"线程1").start();

        new Thread(()->{
            synchronized (lock2){
                System.out.println(Thread.currentThread().getName()+"获取资源2");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                System.out.println(Thread.currentThread()+"等待获取资源1");
                synchronized (lock1){
                    System.out.println(Thread.currentThread()+"获取资源1");
                }
            }


        },"线程2").start();


}
}

二.线程间通信的几个基本方法

1.wait() ;调用wait()方法的线程将进入等待状态,直到收到其他线程通知或被中断

2.wait(long timeout);超时等待一段时间,可能因为超时推出,也可能因为其他线程的调用退出,实际调用native方法的wait(0)表示一直等待

3.notify();通知一个处于wait状态的线程,使其从wait方法返回,如果有多个线程处于wait,只会随机唤醒一个,不能指定唤醒哪个线程

4.notifyAll();唤醒所有处于wait状态的线程

注意:上述的等待唤醒都必须获取对象的synchronized锁;等待和通知的线程必须获取的是同一对象的锁,才能基于synchronized构建等待/唤醒机制

举例:银行卡存取钱

//新建银行卡实体类
public class BankCard {
     private int balance;
     private boolean flag;//true:表示卡中有钱。  false:卡中没钱

     //存钱功能: 为整个方法上锁。
     public synchronized void save(int money){
            if(flag==true){
                try {
                    this.wait(); //调用了wait 那么当前线程就会是否锁资源,并且进入等待队列中。等待队列中的线程需要其他线程调用notify来唤醒等待队列中的线程,参与下次锁的竞争
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            balance=balance+money;
            System.out.println(Thread.currentThread().getName()+"往卡中存入了"+money+";卡中余额:"+balance+"元");
            flag=true;
            //唤醒--等待队列中的线程对象.随机唤醒一个
           this.notifyAll();
     }

     //取钱功能
    public synchronized void take(int money){
          if(flag==false){
              try {
                  this.wait(); //调用了wait 那么当前线程就会是否锁资源,并且进入等待队列中。等待队列中的线程需要其他线程调用notify来唤醒等待队列中的线程,参与下次锁的竞争
              } catch (InterruptedException e) {
                  e.printStackTrace();
              }
          }

          balance=balance-money;
          System.out.println(Thread.currentThread().getName()+"从卡中取出"+money+";卡中余额:"+balance+"元");
          flag=false;
          this.notifyAll();
    }
}

//存钱线程
public class SaveTask implements Runnable{

    private BankCard bankCard;
    public SaveTask(BankCard b){
         bankCard=b;
    }
    public void run() {
        for(int i=0;i<10;i++){
             bankCard.save(1000);
        }
    }
}
//取钱线程
public class TakeTask implements Runnable {

    private BankCard bankCard;

    public TakeTask(BankCard b) {
        bankCard = b;
    }

    public void run() {
        for (int i = 0; i < 10; i++) {
              bankCard.take(1000);
        }
    }
}
//测试

public class Test {
    public static void main(String[] args) {
          BankCard bankCard=new BankCard();
          SaveTask s=new SaveTask(bankCard); //存钱任务
          TakeTask t=new TakeTask(bankCard); //取钱任务

          Thread t01=new Thread(s,"存");
          Thread t02=new Thread(t,"取");


          t01.start();
          t02.start();

    }
}

三.线程的状态

1.NEW;创建一个新的线程对象

2.RUNNABLE;Java线程中将就绪(ready)和运行中(running)两种状态笼统的称为“运行”。 线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取CPU的使用权,此时处于就绪状态(ready)就绪状态的线程在获得CPU时间片后变为运行中状态(running)

3.BLOCKED;阻塞状态

4.WAITING;进入该状态的线程需要等待其他线程做出一些特定动作(通知或中断)

5.TIMED_WAITING;该状态不同于WAITING,它可以在指定的时间后自行返回

6.TERMINATED;终止,表示该线程执行完毕

四.线程池

1.newCachedThreadPool;创建一个可变线程池

创建一个可缓存的无界线程池,如果线程池长度超过处理需要,可灵活回收空线程,若无可回收,则新建线程。当线程池中的线程空闲时间超过60s,则会自动回收该线程,当任务超过线程池的线程数则创建新的线程,线程池的大小上限为Integer.MAX_VALUE,可看作无限大。

2.newFixedThreadPool;一个指定大小的线程池,可控制线程的最大并发数,超出的线程会在LinkedBlockingQueue阻塞队列中等待

3.newSingleThreadExecutor;单一线程池,只有一个线程保证所有的任务按照指定顺序(FIFO,LIFO,优先级)执行,所有的任务都保存在队列LinkedBlockingQueue中,等待唯一的单线程来执行任务。

4.newScheduledThreadPol;延迟线程池,可以指定线程池的核心线程数,支持定时及周期性任务的执行

5.newThreadPoolExecutor;原生模式创建先线程池(灵活,推荐使用)

int corePoolSize,核心线程的个数

int maximumPoolSize,最多的线程的个数

long keepAliveTime,线程空闲时间

TimeUnit unit,空闲的时间

BlockQueue<Runnable>workQueue,等待队列

//原生线程池举例
BlockingQueue<Runnable> workQueue=new ArrayBlockingQueue(5);//最多5等待的任务
ThreadPoolExecutor executor=new ThreadPoolExecutor(5,10,10,TimeUnit.SECONDS,workQueue);
//灵活:
for(int i=0;i<25;i++){
    executor.submit(new Runnable() {
        public void run() {
            System.out.println(Thread.currentThread().getName());
        }
    });
}

补充:

1.Executor: 它是线程池的根接口
2. void execute(Runnable command):执行Runnable类型的任务。
3.ExecutorService: 它是Executor的子接口。
4.  void shutdown():关闭线程池。需要等任务执行完毕。
5.shutdownNow(); 立即关闭线程池。 不在接受新的任务。
6.isShutdown(): 判断是否执行了关闭。
7.isTerminated(): 判断线程池是否终止。表示线程池中的任务都执行完毕,并且线程池关闭了
8.submit(Callable<T> task);提交任务,可以提交Callable
9.submit(Runnable task): 提交任务,可以提交Runnable任务

五.Callable创建线程

Callable与Runnable类似,但是Callable能依赖FutureTask类获取返回值,也可直接使用线程池

代码实现:

package ss;

import java.util.Date;
import java.util.concurrent.*;

public class Callable {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //使用线程池实现
        ExecutorService executorService= Executors.newSingleThreadExecutor();
        Future<Integer> submit = executorService.submit(new MyCallable());
        System.out.println(submit.get());
    }
}
class MyCallable implements java.util.concurrent.Callable<Integer>{

    @Override
    public Integer call() throws Exception {
        int sum=0;
        for (int i = 0; i < 10; i++) {
            sum+=i;
        }
        return sum;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值