多线程

三种实现方式:

  • 继承Thread类
  • 实现Runnable接口
  • 利用Callable和Futrue接口

继承Tread类实现多线程:

  1. 定义一个MyThread类继承Thread类
  2. 在MyThread类中重写run()
  3. 创建MyThread类的对象
  4. 启动线程
public class MyThread extends Thread{
    @Override
    public void run() {
        //代码就是线程开启后执行的代码
        for (int i = 0; i <100 ; i++) {
            System.out.println("线程开启了"+i);
        }
    }
}
public class Demo {
    public static void main(String[] args) {
        MyThread t1= new MyThread();
        MyThread t2= new MyThread();
        t1.start();
        t2.start();
    }

}

  为什么重写run()?

    run()是用来封装被线程执行的代码

  run()和start()有什么区别?

    run():封装线程执行的代码,直接调用,相当于普通方法的调用,并没有开启线程。

    start():启动线程;然后由JVM调用此线程的run()方法。

 

 

通过Runnable接口实现多线程:

  1. 定义一个类MyRunnable实现Runnable接口
  2. 在MyRunnable类中重写run()方法
  3. 创建MyRunnable类的对象
  4. 创建Thread类的对象,把MyRunnable对象作为构造方法的参数
  5. 启动线程

 

public class MyRunnable implements Runnable {
    @Override
    public void run() {
        //线程启动后执行的代码
        for (int i = 0; i < 100; i++) {
            System.out.println("第二种方式实现多线程" + i);
        }
    }
}

  

public class Demo {
    public static void main(String[] args) {
        //创建了一个参数对象
        MyRunnable mr = new MyRunnable();
        //创建了一个线程对象,并把参数传递给这个线程
        //在线程启动后,执行的就是参数里的run()方法
        Thread t1=new Thread(mr);
        //开启线程
        t1.start();

        MyRunnable mr2 = new MyRunnable();
        Thread t2 = new Thread(mr2);
        t2.start();

    }
}

  

通过Callable和Future实现多线程:

  1. 定义一个MyCallable类实现Callable接口
  2. 在MyCallable类中重写call()方法
  3. 创建MyCallable类的对象
  4. 创建Future的实现类FutureTask对象,把MyCallable对象作为构造方法的参数
  5. 创建Thread类的对象,把FutureTask对象作为构造方法的参数
  6. 启动线程
  7. 调用get()方法获取线程之后的结果
public class MyCallable implements Callable<String> {
    @Override
    public String call() throws Exception {
        for (int i = 0; i < 100; i++) {
            System.out.println("跟女孩表白的次数"+i);
        }
        //返回值表示线程运行完毕后的结果
        return "答应";
    }
}

  

public class Demo {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //线程开启后需要执行call方法
        MyCallable mc = new MyCallable();
        //可以获取线程执行完毕后的结果,也可以作为参数传递给Thread对象
        FutureTask<String> future = new FutureTask(mc);
        //创建线程对象
        Thread t1=new Thread(future);

        t1.start();
        //获得线程运行后的结果,如果线程没有结束,get方法会一直死等
        String s = future.get();
        System.out.println(s);

    }
}s

 

三种方式对比 优点 缺点
实现Runnable、Callable接口   扩展性强,实现该接口的同时还可以继承其他的类。 编程相对复杂,不能直接使用Thread类中的方法。
继承Thread类 变成比较简单,可以直接使用Thread类中的方法。 可以扩展性较差,不能再继承其他的类。

 

Thread类中常用方法

获取和设置线程的名称

  获取线程名字  

    String getName():返回此线程的名称。

  设置线程名字

    void setName(String name):将此线程的名称更改为等于参数name。

    通过构造方法也可以设置线程名称。

public class MyThread extends Thread{
    public MyThread() {
    }
    public MyThread(String name) {
        super(name);
    }

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(getName()+"@@@"+i);
        }
    }
}

  

public class Demo {
    public static void main(String[] args) {
        //线程是有默认的名字的,格式:Thread-数字
        MyThread t1 = new MyThread("小菜");
        MyThread t2 = new MyThread();

        //t1.setName("小菜");
        t2.setName("小果");
        t1.start();
        t2.start();
    }
}

  

获得当前线程的对象

  public static Thread cureentThread():返回当前正在执行的线程对象的引用

public class MyRunnable implements Runnable {
    @Override
    public void run() {
        //线程启动后执行的代码
        for (int i = 0; i < 100; i++) {
        //获取当前线程的名字 System.out.println(Thread.currentThread().getName()+"第二种方式实现多线程" + i); } } }

  

线程休眠

  public static void sleep(long time):让线程休眠指定的时间,单位为毫秒。

public class Demo {
    public static void main(String[] args) throws InterruptedException {
        System.out.println("睡觉前");
        Thread.sleep(10000);
        System.out.println("睡醒了");
    }
}

 

线程调度

  多线程的并发运行:计算机的CPU在任意时刻只能执行一条机器指令,每个线程只有获得CPU的使用权才能执行代码。

           各个线程轮流获得CPU的使用权,分别执行各自的任务。

  线程有两种调度模型:

          分时调度模型:所有线程轮流使用CPU,平均分配每个线程占用CPU的时间片。

          抢占式调度模型:优先让优先级高的线程使用CPU,如果线程的优先级相同,那么会随机选择一个,优先级高的线程获取的CPU时间片相对多一些。

  线程的优先级:

          public final void setPriority(int newPriority):设置线程的优先级

          public final  int  getPriority(): 获取线程的优先级

 

public class MyCallable implements Callable<String> {
    @Override
    public String call() throws Exception {
        for (int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName()+"-----"+i);
        }
        return "success!";
    }
}

  

public class Demo {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //线程优先级1-10,默认为5
        MyCallable mc1 = new MyCallable();
        MyCallable mc2 = new MyCallable();
        FutureTask<String> ft1 = new FutureTask(mc1);
        FutureTask<String> ft2 = new FutureTask(mc2);
        Thread t1 = new Thread(ft1);
        Thread t2 = new Thread(ft2);
        t1.setName("飞机");
        t2.setPriority(8);
        System.out.println(t1.getPriority());
        System.out.println(t2.getPriority());
        t2.setName("坦克");
        t1.start();
        t2.start();
        String s = ft1.get();
        System.out.println(s);
    }
}

  

  后台线程、守护线程

    public final void setDaemon(boolean on):设置守护线程。

public class MyThread1 extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println(getName() + "-----" + i);
        }
    }
}

  

public class MyThread2 extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println(getName() + "-----" + i);
        }
    }
}

  

public class Demo {
    public static void main(String[] args) {
        MyThread1 thread1 = new MyThread1();
        MyThread2 thread2 = new MyThread2();
        thread1.setName("男神");
        thread2.setName("备胎");
        //thread2设置成守护线程
        //但普通线程执行完毕后,守护线程也没有运行下去的必要了(不会立马停止)
        thread2.setDaemon(true);
        thread1.start();
        thread2.start();
    }
}

  

posted @ 2022-05-08 17:22  格兰芬多剁剁剁  阅读(33)  评论(0)    收藏  举报