线程

作者: 冯宏志 | 来源:发表于2020-12-13 15:20 被阅读0次
    线程的创建和启动方式一
    1. 创建一个继承于Thread类的子类
    2. 重写Thread类的run():将此线程执行的操作写在run()中
    3. 创建Thread类的子类对象
    4. 通过此对象调用start()
      ①启动当前线程
      ②调用当前线程的run()
    • 例子:遍历10000以内的所有偶数
    public class ThreadTest {
        public static void main(String[] args) {
            MyThread thread1 = new MyThread();
            //启动线程
            thread1.start();
    
            //主线程
            for(int i = 0;i <= 100;i++) {
                if (i % 2 == 0)
                    System.out.println(i + "*********main*********");
            }
        }
    }
    
    class MyThread extends Thread{
        @Override
        public void run() {
            super.run();
            for(int i = 0;i <= 10000;i++){
                if(i % 2 == 0)
                System.out.println(i);
            }
        }
    }
    
    • 创建线程的简便方式
    //创建Thread类的匿名子类方式
            new Thread(){
                @Override
                public void run() {
                    super.run();
                    for(int i = 0;i <= 100;i++){
                        if(i % 2 == 0)
                            System.out.println(i + "thread1");
                    }
                }
            }.start();
    
    • 问题一:不能通过对象直接调用run()来启动线程,必须要用对象的start()。
    • 问题二:再启动一个线程,不可以让已经start()的对象去启动,要再创建一个对象,然后让他start()
    线程的常用方法

    start():启动当前线程,调用当前线程的run();
    run():通常需要重写Thread类中的此方法,将创建的线程要执行的操作声明在此方法中
    currentThread():静态方法,返回当前代码的线程
    getName():获取当前线程的名字
    setName():设置当前线程的名字
    yield():释放当前CPU执行权,让当前线程失去CPU
    join():在线程a中调用线程b的join()方法,此时线程a进入阻塞状态,直到线程b执行完以后,线程a才结束阻塞状态。
    sleep(long millitime):让当前线程阻塞millitime毫秒
    isAlive():判断当前线程是否存活

    线程的调度
    • 线程的优先级
      MAX_PRIORITY = 10
      NORM_PRIORITY = 5:默认的优先级
      MIN_PRIORITY = 1

    • 获取和设置当前线程的优先级
      getPriority()
      setPriority(int p)
      说明:高优先级的线程高概率的情况下被执行。并不意味着只有当高优先级的线程执行完以后,低优先级的线程才执行。

    创建线程的方式二:实现Runnable接口
    1. 创建一个实现了Runnable接口的类
    2. 实现类去实现Runnable中的抽象方法:run()
    3. 创建实现类的对象
    4. 将此对象作为参数传递到Thread类的构造器中,创建Thread类的对象
    5. 通过Thread类的对象调用start()
    public class ThreadTest1 {
        public static void main(String[] args) {
            MThread thread1 = new MThread();
            Thread t1 = new Thread(thread1);
    
            MThread thread2 = new MThread();
            Thread t2 = new Thread(thread2);
    
            t1.start();
            t2.start();
    
        }
    }
    
    class  MThread implements Runnable{
    
        @Override
        public void run() {
            for(int i = 0;i <= 100;i++){
                if(i % 2 == 0)
                    System.out.println(Thread.currentThread().getName() + "*********" + i);
            }
        }
    }
    
    比较创建线程的两种方式
    • 开发中,优先选择实现Runnable的方式,
      原因:
      1、实现的方式没有类的单继承性的局限性
      2、实现的方式更适合来处理多个线程有共享数据的情况

    • 二者联系
      public class Thread implements RunnableThread类也实现了Runnable接口

    • 相同点
      都需要重写run(),将线程要执行的逻辑声明在run()中

    线程的生命周期
    image.png
    线程的同步
    • 当一个线程a在操作共享数据的时候,其他线程不能参与进来,直到线程a操作完共享数据,其他线程才能操作共享数据
    • 方式一 synchronize
    synchronize(同步监视器){
      //需要被同步的代码
    }
    

    说明:
    1、操作共享数据的代码,即为需要被同步的代码 不能包多也不能包少
    2、同步监视器,俗称:锁。任何一个类的对象都可以充当锁
    要求多个线程必须拥有同一把锁
    补充:
    在实现Runnable接口创建多线程的方式中,我们还可以考虑使用this充当同步监视器
    在继承Thread类创建多线程的方式中,慎用this充当同步监视器。可以考虑使用当前类充当同步监视器。

    • 方式二:同步方法
      如果操作共享数据的代码完整的声明在一个方法中,我们不妨将此方法声明同步的。

    总结:
    1、同步方法仍然涉及到同步监视器,只是不需要我们显式的声明
    2、非静态的同步方法,同步监视器是this
    3、静态的同步方法,同步监视器是当前类本身

    相关文章

      网友评论

          本文标题:线程

          本文链接:https://www.haomeiwen.com/subject/dyiviktx.html