多线程

  • 多线程
  • 进程:正在运行的一个程序 系统会为这个进程分配独立的内存资源
  • 线程:具体执行任务的最小单位
  • 一个进程最少拥有一个线程(主线程 运行起来就执行的线程)
  • 线程之间是共享内存资源的(进程申请的)
  • 线程之间可以通信(数据传递 :多数为主线程和子线程)
  • 每一个线程都有自己的运行回路(生命周期)
线程的生命周期状态:
  • NEW:新建 线程刚被创建好
  • RUNNABLE:就绪状态 只要抢到时间片就可以运行这个线程
  • BLOCKED,:堵塞状态 sleep wait
  • WAITING,:等待状态 wait
  • TIMED_WAITING,
  • TERMINATED;终止
为什么需要创建一个子线程
  • 如果在主线程中存在又比较耗时的操作:下载视频 上传文件 数据处理
  • 这些操作会阻塞主线程 ,后面的任务必须等这些任务处理完毕
  • 之后才能执行 用户体验比较差
  • 为了不阻塞主线程 需要将耗时的任务放入子线程中
如何创建一个子线程
  • join :让当前这个线程阻塞 等join 的线程执行完毕在执行
  • setName:设置线程名称
  • getName:获取线程名称
  • currentThread:获取当前运行的线程对象
  • start:开启任务
.方法一 :定义一个类继承于Thread 实现run方法

main方法里面执行的代码 是在主线程里面执行的
主线程的名称是main 由系统定义 自己不能定义

获取线程名称

String name=Thread.currentThread().getName();
System.out.println(name);

创建对象 子线程

TestThread tt=new TestThread();

设置子线程的名字

tt.setName("子线程");

开启任务

对于同一个线程 不能开启两次
tt.start();
tt1=new TestThread();
tt1.start();

主线程

for (int i = 0; i < 5; i++) {
System.out.println("main"+i);

创建一个类 用于实现子线程
class TestThread extends Thread{
 // 实现run方法
//  方法里面就是具体实现的代码
 @Override
    public void run() {
        String name=Thread.currentThread().getName();
        for (int i=0;i<100;i++)
        {
            System.out.println(name+i);
          
                }
   super.run();
       }
    }

方法二:实现runable接口 实现run方法
  • 1.创建任务 创建实现runable接口
  • 2.使用Thread 实现这个接口
  • 3.开启任务 start

实现方法1.接口 抽象方法
创建一个任务:创建一个类实现Runable接口
PXDEThread pt=new PXDEThread();
//使用Thread操作这个任务
Thread t=new Thread(pt);
t.setName("子线程");

    t.start();
   Thread t1=new Thread(pt);
    t1.setName("子线程1");
    t1.start();
class  PXDEThread implements Runnable
{
      public void run() {
        for (int i = 0; i < 100; i++) {
          System.out.println(Thread.currentThread().getName()+"   "+i);
        }
    }
}

实现方法2:
这个任务只使用一次
Thread t=new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName()+" "+i);
}
}
});
t.setName("子线程");
t.start();

        //创建线程的同时  开启线程任务
        //不需要操作线程本身
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 10; i++) {
                    System.out.println(Thread.currentThread().getName()+"   "+i);
              }
            }
        }).start();
        //使用Lambda
        //不建议:阅读性太差
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                System.out.println(Thread.currentThread().getName() + "   " + i);
            }
        }).start();

线程安全

  • synchronized Lock 加锁解锁
  • synchronized 同步监听器 需要一把锁
  • 任何一个对象都有一把锁/监听器
  • 如果多个线程操作同一个代码块 ,并需要是同步的
  • 那么必须操作同一个对象的同一把锁
  • synchronized (监听器/对象/锁){
  • 需要同步的代码
  • }
  • 解决方法
  • 1.同步代码块
  • 2.同步方法 同步监听器是当前对象本身
  • 必须确保多个对象调用的是同一个对象
  • public synchronized void test()
  • 本质就是同步代码快
  • 等价于
  • synchronized (this)
  • {
  • text();
  • }
synchronized (obj){
 /需要同步的代码
                if (num>0)
                {
                    System.out.println(name+"出票"+num);
                    num--;

                    try{
                        //唤醒其他线程
                        obj.notify();
                        //当前线程等待
                        obj.wait();
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }else {
                    break;
                }
            }
  • 死锁
  • Lock
  • ReentrainLock 可重入锁
  • 使用接口实现线程间数据的回调
  • Person 类
  • 线程里面 Agent 类
  • 1.如何创建一个线程
  • 2.线程的同步
  • 3.主线程和子线程之间使用接口回调数据
  • 4.线程之间的通信:synchronized (wait notifi notifiall)
  • ReentranLock lock;
  • Condition c=lock.newCondition();
  • await single singleAll

火车站买票
        //全国的卖票系统  就一个
        Ticket ticket=new Ticket("重庆");
        Thread tr=new Thread(ticket);
        tr.start();
        Ticket ticket1=new Ticket("上海");
        Thread tr1=new Thread(ticket1);
        tr1.start();
//用于卖票的任务
class  Ticket implements Runnable
{
    //定义所有火车票的数量
   public static int num=20;
   String name;
   public  Ticket(String name)
   {
       this.name=name;
   }
   static  final Object obj=new Object();
   //创建一个可重新载入的锁
    static ReentrantLock lock=new ReentrantLock();
    @Override
    public void run() {
        for (int i = 0; i < 20; i++) {
            //判断有没有票
            lock.lock();
            if (num > 0) {
                System.out.println(name + "出票" + num);
                num--;

                try {

                } catch (Exception e) {
                    e.printStackTrace();
                }
            } else {
                break;
            }
            lock.unlock();
            }

        }
    }

你可能感兴趣的:(多线程)