线程、线程通信

一。线程
1.匿名内部类方式实现线程

public class NmThred {
    public static void main(String[] args) {
        Thread t=new Thread("kk"){//匿名内部类来构造Thread线程对象

            public void run() {
                Thread t=Thread.currentThread();
                for(int i=0;i<10;i++){
                    System.out.println(t.getName()+i);
                }
            }
        };
        t.start();

        Runnable run=new Runnable() {//通过匿名内部类来构造初始化Runnable线程任务
            @Override
            public void run() {
                Thread t=Thread.currentThread();
                for(int i=0;i<10;i++){
                    System.out.println(t.getName()+i);
                }
            }
        };
      Thread tt=new Thread(run,"lll");//线程任务来创建线程对象
      tt.start();
    }
}

线程的执行顺序, 是不固定的
线程Thread的构造方法:
1.new 自定义线程类();自定义类的构造方法, 随意
2.new Thread(); 无参构造器
3.new Thread(String); String->指定的线程名
4.new Thread(Runnable); Runnable->线程任务
5.new Thread(Runnable, String);Runnable->线程任务, String->指定的线程名

2.线程Thread常用API:

  • 1.static Thread currentThread(): 获得当前正在执行的线程对象
    2.String getName(): 获得线程对象的名字, 线程在创建时可以指定名字, 也可以默认分配名字
    3.int getPriority(): 返回此线程的优先级
    void setPriority(int): 设置线程的优先级
    4.boolean isDaemon(): 测试这个线程是否是守护线程
    void setDaemon(boolean): 设置这个线程是守护线程
    5.static void sleep(long): 线程休眠指定时间
    会有一个已检查异常, 所以必须要 try-catch
    6.void join(): 等待调用这个方法的线程结束, 再继续后续代码
    会有一个已检查异常, 所以必须要 try-catch
    7.static void yield(): 主动放弃cpu的时间片

3.优先级:改变CPU分配时间片的概率,只是概率提升,本质上没啥用

public class Demo {
    public static void main(String[] args) {
        Runnable run = new Runnable() {
            @Override
            public void run() {
                Thread t = Thread.currentThread();
                for (int i = 0; i < 10; i++) {
                    System.out.println(t.getName() + ": " + i);
                }
            }
        };

        Thread t1 = new Thread(run, "线程1");
        Thread t2 = new Thread(run, "线程2");
        Thread t3 = new Thread(run, "线程3");
        // 默认优先级, 都是5
        /*System.out.println("t1: " + t1.getPriority());
        System.out.println("t2: " + t2.getPriority());
        System.out.println("t3: " + t3.getPriority());*/

        t1.setPriority(Thread.MIN_PRIORITY);
        t3.setPriority(10); // 最大优先级
        t1.start();
        t2.start();
        t3.start();
    }
}

4.线程延迟、守护线程
守护线程 - 前台线程
当所有的前台线程结束, 守护线程也会自动结束

public class ThreadApi {
    public static void main(String[] args) {
        Runnable run1=new Runnable() {
            @Override
            public void run() {

                for(int i=0;i<50;i++){
                    try {
                        Thread.sleep(100);//制造延迟, 让线程暂停一下

                    }catch (Exception e){
                    }
                    System.out.println("块跳");
                }
                System.out.println("我跳了,你骗我");
            }
        };
        Runnable run2=new Runnable() {
            @Override
            public void run() {
                while (true){
                    try {
                        Thread.sleep(1000);
                    }catch (Exception e){}
                    System.out.println("you jump i jump");
                }
            }
        };
        Thread t1=new Thread(run1,"lucy");
        Thread t2=new Thread(run2,"jack");
        System.out.println("是否为守护线程"+t2.isDaemon());//判断是否为守护线程
        t2.setDaemon(true);//设置为守护线程。守护线程会在前台线程结束后结束
        t1.start();
        t2.start();
    }
}

5.线程同步 - 多个线程, 共享资源
1.synchronized: 同步锁, 只能同时被一个线程持有,
当线程执行完这个方法, 才会将锁释放
加到方法上, 同步方法锁
加到代码上, 借助对象, 通常是this,
确保同步的线程, 对象共享即可
2.Lock - 接口
实现类: ReentrantLock lock = new ReentrantLock();
加锁: 锁对象.lock();
解锁: 锁对象.unlock();

public class Ticket {
    public int count=100;
    //①synchronized在方法上加锁,(同步方法锁)。使线程安全
    /*public synchronized void saleTicket(){
        if(count==0){
            throw new RuntimeException("票无!");
        }
        System.out.println(Thread.currentThread().getName()+count);
        count--;
    }*/

    //②synchronized对象锁
    /*public void saleTicket(){
        synchronized (this){
            if(count==0){
                throw new RuntimeException("票无!");
            }
            System.out.println(Thread.currentThread().getName()+count);
            count--;
        }
    }*/

    //③Lock锁
    ReentrantLock lock=new ReentrantLock();//创建lock锁对象
    public void saleTicket(){
       // ReentrantLock lock=new ReentrantLock();//创建lock锁对象
        lock.lock();//上锁
        if(count==0){
            throw new RuntimeException("票无!");
        }
        System.out.println(Thread.currentThread().getName()+count);
        count--;
        lock.unlock();//开锁
    }
}

synchronized使用原则: 尽量将少的代码加锁
可以只将一部分代码加锁, 同步代码锁, 需要借助一个对象
加锁的对象: 可以是任意对象, 只需要确保多个同步的线程, 对象唯一就可以了
通常使用this对象
对象锁: 一个对象只能加一把锁, 并且只能同时被一个线程持有
6. 图片加载和显示两个线程:

  • List item 1.线程1 负责图片的加载任务. 1%~100% -> 加载完成
    2.线程2 负责图片的显示任务. 要求图片加载完才能显示
    线程1 和 线程2 是同时开启的 start()
public class Demo {
    public static void main(String[] args) {
        Picture picture = new Picture();
        Thread load = new Thread(){
            public void run() {
                System.out.println("图片开始加载....");
                for (int i = 0; i < 100; i++) {
                    System.out.println("正在加载: " + (i+1) + "%");
                }

                System.out.println("图片加载完成");
            }
        };
        Thread show = new Thread(){
            public void run() {
                System.out.println("等待图片加载完成....");
                // 等待 load 线程结束
                try {
                    load.join();//join可以可以阻塞此部分程序
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("显示图片!");
            }
        };

        load.start();
        show.start();
    }
}

在这里插入图片描述

二。线程通信:
两个线程有共享数据, 线程之间有动作交互
wait(): 等待
notify(): 唤醒
①.

  • 图片加载/下载 和 图片显示两个线程:
    1.线程1 先负责图片的加载任务. 1%~100% -> 加载完成
    再负责图片的下载任务. 1%~100% -> 下载完成
    要求图片显示完才能下载
    2.线程2 负责图片的显示任务. 要求图片加载完才能显示
public class Load extends Thread {
    Picture picture;

    public Load(Picture picture, String name) {
        super(name);
        this.picture = picture;
    }
    @Override
    public void run() {
        //图片开始加载
        System.out.println("图片开始加载");
        for(int i=0;i<100;i++){
            System.out.println("图片加载了"+i+"%");
        }
        System.out.println("图片加载完成");
        //加载完图片修改lode状态
        picture.isLoad=true;
        加载好要唤醒show
        synchronized (picture){
            picture.notify();
        }
        //等待图片显示完成
        if(!picture.isShow){
            synchronized (picture){
                try {
                    picture.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        //图片显示 notif,开始下载图片
        System.out.println("开始下载图片...");
        if(picture.isShow){
           for (int i=0;i<100;i++){
               System.out.println("图片正在下载"+i+"%");
           }
        }
        System.out.println("图片下载完成");
    }
}

public class Show extends Thread{
    Picture picture;
    public Show(Picture picture, String name) {
        super(name);
        this.picture=picture;
    }

    @Override
    public void run() {
        System.out.println("等待图片加载完成....");
        //图片没加载完
        if(!picture.isLoad){
            synchronized (picture){
                try {
                    picture.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        //图片加载完成,显示图片
        System.out.println("显示图片");
        if(picture.isLoad){
            try {
                Thread.sleep(3000);//图片显示3秒
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //改变图片显示状态
        picture.isShow=true;
        //图片显示完成,开始下载,唤醒下载线程
      synchronized (picture){
          picture.notify();
      }

    }
}

public class Picture {
    public boolean isLoad;
    public boolean isShow;
}

public class Main {
    public static void main(String[] args) {
        Picture picture=new Picture();
        Load load=new Load(picture,"load");
        Show show=new Show(picture,"show");
        load.start();
        show.start();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值