day13——线程

并行和并发

并行:同时执行
并发:交替执行

进程和线程

进程:正在执行的程序
线程:程序的执行路径,一个程序中可以包含多条执行路径(多线程程序)
  	举例:飞秋、迅雷、360安全管家

线程的实现方式

继承Thread方式

实现步骤:
  1.写一个子类继承Thread
  2.复写run方法(线程的执行代码)
  3.创建Thread的子类对象
  4.调用start方法,开启线程
public class DownloadThread extends Thread{
  @Overried
  public void run(){
    	for(int i=0;i<=100;i++){
        	System.out.println("正在下载..."+i+"%");
      }
  }
}
public class ThreadDemo1{
  public static void main(Stirng[] args){
    	//3.创建Thread的子类对象
      DownloadThread dt1=new DownloadThread();
    	dt1.start();
    
    	DownloadThread dt2=new DownloadThread();
    	d2t.start();
  }
}

实现Runnable方式

实现步骤:
  1.写一个子类实现Runnable接口
  2.复写run方法(线程的执行代码)
  3.创建Thread对象,把Runnable对象当做参数传递给Thread
  4.调用start方法,开启线程
public class DownloadRunnable implements Runnable{
    //run方法中是线程的执行代码
    @Override
    public void run(){
        for(int i=0;i<=100;i++){
            //先获取当前正在执行的线程Thread对象,再通过Thread对象获取线程的名称
            String name= Thread.currentThread().getName();
            System.out.println(name+"正在下载..."+i+"%");
        }
    }
}
public class ThreadDemo2 {
    public static void main(String[] args) {
        //创建Runnable的实现类对象
        DownloadRunnable dr=new DownloadRunnable();

        //创建线程对象
        Thread t1=new Thread(dr);
        t1.start();

        //创建线程对象
        Thread t2=new Thread(dr);
        t2.start();
    }
}

实现Callable方式

实现步骤:
  	1.写一个实现类实现Callable
  	2.复写call方法(线程的执行代码,有返回值)
  	3.创建Callable的实现对象,传递给FutureTask
  	4.创建Thread对象,接受FutureTask对象
  	5.调用start方法,开启线程
  
  	6.调对象FutureTask的get方法,获取先的执行结果。
public class DownloadCallable implements Callable<String> {
    //run方法中是线程的执行代码
    @Override
    public String call(){
        for(int i=0;i<=100;i++){
            //先获取当前正在执行的线程Thread对象,再通过Thread对象获取线程的名称
            String name= Thread.currentThread().getName();
            System.out.println(name+"正在下载..."+i+"%");
        }

        return "完毕";
    }
}
public class ThreadDemo3 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //创建Runnable的实现类对象
        DownloadCallable dr=new DownloadCallable();

        //创建FutrueTack对象
        FutureTask<String> task1=new FutureTask<String>(dr);
        //创建线程对象
        Thread t1=new Thread(task1);
        t1.start();

        //创建FutrueTack对象
        FutureTask<String> task2=new FutureTask<String>(dr);
        //创建线程对象
        Thread t2=new Thread(task2);
        t2.start();

        //获取执行结果
        String s1 = task1.get();
        String s2 = task2.get();
        System.out.println(s1);
        System.out.println(s2);
    }
}

三种实现方式的区别

1.实现Runable方式:实现接口的同时,也可以继承其他类。
2.继承Thread方法:由于Java是单继承,不能再去继承其他类。
3.实现Callalble方式:有回值

在这里插入图片描述

Thread类的方法

public static void sleep(long time)
  让线程休眠指定的毫秒值
public void setPriority(int number)
  设置线程优先级的方法(1~10优先级越高,执行到的几率越高)
public void setDaemon(boolean true)
  设置线程为守护线程。当普通线程执行完毕后,守护线程也会根这结束。

线程安全问题

产生的原因:
  	多个线程在访问共享数据时,可能一个线程还没有执行完,执行权就被另一个线程抢走了,就可能有线程安全问题

解决方案
  1.同步代码块
  		//任意对象,要保证唯一
  		synchronized(锁对象){
  				有安全问题的代码
			}
	
  2.同步方法
    	//同步方法的锁对象是: this
    	public synchronized  void method(){
    
  		}
			//静态的同步方法锁对象是:字节码对象
			public synchronized static void method(){
    
  		}
    
  3.Lock锁
     //创建锁对象
     Lock lock=new ReentrantLock();
		 //上锁
		 lock.lock();
				...有线程安全问题的代码...
     //解锁
     lock.unlokc();

死锁问题

死锁的问题是因为同步代码块不合理的嵌套导致的,两个线程相互持有多方的锁,导致两个线程都不能执行。

在这里插入图片描述

生产者和消费者

生产者和消费者是一个很经典的解决供需关系的一个案例。

生产者(线程)
  判断是否已经有数据
  		有:等待
  		没有:生产产品,把消费者唤醒,把产品的状态改成有
  	
消费者(线程)
  判断是否已经有数据
  		没有:等待
  		有:消费这个产品,把产品状态改为没有,唤醒生产者
  
产品(共享数据)
  产品的状态
  • 共享数据
public class Desk{
  private boolean flag; //数据的状态
  private final Object lock=new Object(); //锁对象
  private int count=10; //控制线程执行次数
  
  //构造方法,get和set方法,自己快捷键生成
}
  • 生产者线程
//厨师
public class Cooker extends Thread{
  	private Desk desk;
  	//使用构造方法给成员变量赋值
  	private Cooker(Desk desk){
      this.desk=desk;
    }
  
  	@Override
  	public void run(){
        while(true){
          if(deskc.getCount()==0){
            break;
          }else{
             synchronized(desk.getLock()){
              //判断是否已经有数据(汉堡包)
              if(desk.isFlag()){
                  //有:等待
                  desk.getLock().wait();
              }else{
                 //没有:生产产品,把产品的状态改成有(true),把消费者唤醒,
                 System.out.println("厨师正在生产汉堡包");
                 desk.setFlag(true);
                 desk.getLock().notifyAll();
              }
            }
          }
        }
    }
}
  • 消费者线程
public class ChiHuo extends Thread{
  	private Desk desk;
  	//使用构造方法给成员变量赋值
  	private ChiHuo(Desk desk){
      this.desk=desk;
    }
  
    @Override
  	public void run(){
      while(true){
        	if(desk.getCount()==0){
              break;
          }else{
            synchronized(desk.getLock()){
              //判断是否已经有数据(汉堡包)
              if(desk.getFlag()){
                //有:消费这个产品,把产品状态改为没有(false),唤醒生产者线程
                System.out.println("吃货开始吃汉堡包");
                desk.setCount(desk.getCount()-1);
                desk.setFlag(false);
                desk.getLock().nofityAll();
              }else{
               	//没有:等待 
                 desk.getLock().wait();
              }
            }
          }
      	}
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值