JAVA线程

843 阅读5分钟

1. 线程创建的两种方法

  • 方法一:
    • 将类声明为Thread的子类
      1. 定义Thread类的子类,并重写该类的run()方法,该run()方法中的方法体代表了线程需要完成的任务,因此把run()方法称为线程执行体
      2. 创建Thread子类的实例,即创建了线程对象
      3. 调用线程对象的start()方法来启动该线程
- SubThread.java
           1.定义一个子线程的类,继承Thread类;
           public class SubThread extends Thread {
            /*
             *2.在子线程类中重写run方法,在run方法中打印子线程的名称;
             */
            public void run() {
             // 打印子线程的名称
             System.out.println("subThread:" + Thread.currentThread().getName());
            }
           }
- ThreadDemo.java
            public class ThreadDemo {
             public static void main(String[] args) {
              // 4.在main方法中打印主线程的名称;
              System.out.println("main:" + Thread.currentThread().getName());
              // 5.在main方法中创建子线程对象;
              SubThread st = new SubThread();
              // 6.调用子线程对象的start方法,开启子线程。
              st.start();
             }
            }

  • 方法二:
    • 声明一个类实现Runnable 接口
      1. 定义Runnable接口的实现类,并重写该接口的run()方法,该run()方法的方法体同样是该线程的线程执行体
      2. 创建Runnable实现类的实例,并以此实例作为Thread的target来创建Thread对象,Thread对象才是真正的线程对象
      3. 调用线程对象的start()方法来启动线程
RunableImpl.java
            //定义一个子任务类,实现Runnable接口
            public class RunableImpl implements Runnable {
                @Override
                public void run() {
                    //在子任务类中重写run方法,在run方法中打印子线程的名称
                    for (int i = 0; i < 10; i++) {
                        System.out.println(Thread.currentThread().getName() + "-子线程" + i);
                    }
                }
            }
demo2Runalbe.java
            //定义一个测试类
            public class demo2Runable {
                public static void main(String[] args) {
                    //创建一个子任务对象
                    RunableImpl run = new RunableImpl();
            
                    //创建一个Thread类的对象,并把子任务对象作为参数传递给Thread类的构造方法
                    Thread t = new Thread(run);
            
                    //调用Thread类的start()方法开启线程
                    t.start();
            
                    //主线程中打印线程名称
                    for (int i = 0; i < 10; i++) {
                        System.out.println(Thread.currentThread().getName() + "-主线程" + i);
                    }
                }
            }

2. 线程中的run方法与start方法区别

  • 线程对象调用run()方法不开启线程,仅是对象调用方法。线程对象调用start()方法开启线程,并让jvm调用run()方法在开启的线程中执行。

3. 实现Runnable接口的优势

  • 适合多个相同的程序代码的线程去共享同一个资源。
  • 可以避免java中的单继承的局限性。
  • 增加程序的健壮性,实现解耦操作,代码可以被多个线程共享,代码和数据独立。
  • 线程池只能放入实现Runable或callable类线程,不能直接放入继承Thread的类。

4. 线程状态

  • NEW(新建) 线程刚被创建,但是并未启动。
  • Runnable(可运行) 线程可以在java虚拟机中运行的状态,可能正在运行自己代码,也可能没有,这取决于操作系统处理器。
  • Blocked(锁阻塞) 当一个线程试图获取一个对象锁,而该对象锁被其他的线程持有,则该线程进入Blocked状态;当该线程持有锁时,该线程将变成Runnable状态。
  • Waiting(无限等待) 一个线程在等待另一个线程执行一个(唤醒)动作时,该线程进入Waiting状态。进入这个状态后是不能自动唤醒的,必须等待另一个线程调用notify或者notifyAll方法才能够唤醒。
  • Timed Waiting(计时等待) 同waiting状态,有几个方法有超时参数,调用他们将进入Timed Waiting状态。这一状态将一直保持到超时期满或者接收到唤醒通知。带有超时参数的常用方法有Thread.sleep 、Object.wait。
  • Teminated(被终止) 因为run方法正常退出而死亡,或者因为没有捕获的异常终止了run方法而死亡。

5. 匿名内部类创建线程

格式:
    new 父类/接口(){
        重复父类/接口中的方法
    };
  • 匿名内部类作用:简化代码
    1. 把子类继承父类,重写父类的方法,创建子类对象合一步完成
    2. 把实现实现类接口,重写接口中的方法,创建实现类对象合成一步完成
      匿名内部类的最终输出:子类/实现类对象,而这个类没有名字
  • 方法一:
public class InnerRunable {
    public static void main(String[] args) {
        /*
            线程实现的第一种方法。继承Thread类,生成子类对象,重写run()方法。调用start()启动线程。
            new Thread(){ }
            大括号内重写run()方法
            返回匿名的Thread子类对象。
         */
        new Thread(){
            @Override
            public void run() {
                for (int i = 0; i < 10; i++) {
                    System.out.println(Thread.currentThread().getName() + "--> override1---" + i);
                }
            }
        }.start();
    }
}    
  • 方法二:
        /*
                Runnabel run = new RunableImpl();//多态
                Thread t = new Thread(run);
                t.start()
         */
       Runnable r =  new Runnable(){
           //重写run方法,设置线程任务
            @Override
            public void run() {
                for (int i = 0; i < 10; i++) {
                    System.out.println(Thread.currentThread().getName() + "--> override2---" + i);
                }
            }
        };
       new Thread(r).start();
  • 简化接口
        //简化接口的方式
       new Thread(new Runnable(){
           //重写run方法,设置线程任务
           @Override
           public void run() {
               for (int i = 0; i < 10; i++) {
                   System.out.println(Thread.currentThread().getName() + "--> override3---" + i);
               }
           }
       }).start();


IDEA快捷键

  • alt+enter 导入包,自动修正代码
  • ctr+y 删除光标当前行
  • ctr+d 复制光标当前行到下一行
  • ctr+alt+L 格式化代码
  • ctr+/ 单选注释
  • ctr+shift+/ 多行注释,再次按的话则取消注释
  • alt+ins 自动生成代码,toString,set,get
  • alt+shift+上下箭头 移动当前行
  • 在IDEA工具中, Ctrl+空格 的快捷键,可以帮助我们补全代码,但是这个快捷键和Windows中的输入法切换快捷 键冲突,需要修改IDEA中的快捷键。
    • File->Settings->keymap->Main menu->code->Completion->Basic
    • 双击 Basic->remove->Ctrl+空格