多线程(优雅)

一些基本概念

线程:基本执行实体

进程:一个进程可以有多个线程

并发:同一时刻交替进行

并行:同一时刻同时进行

进程和线程

进程:是正在运行的程序

独立性:进程是一个能独立运行的基本单位,同时也是系统分配资源和调度的独立单位

动态性:进程的实质是程序的一次执行过程,进程是动态产生,动态消亡的

并发性:任何进程都可以同其他进程一起并发执行线程:是进程中的单个顺序控制流,是一条执行路径

线程:是进程中的单个顺序控制流,是一条执行路径

​ 单线程:一个进程如果只有一条执行路径,则称为单线程程序

​ 多线程:一个进程如果有多条执行路径,则称为多线程程序

通俗来说:多线程就是让程序同时做多件事情,目的是提高效率

实现多线程

方式一:继承Thread类

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

}
public class ThreadDemo {
    public static void main(String[] args) {
        /*
        * 多线程的第一种启动方式:
        *   1. 自己定义一个类继承Thread
        *   2. 重写run方法
        *   3. 创建子类的对象,并启动线程
        * */


        MyThread t1 = new MyThread();
        MyThread t2 = new MyThread();
        MyThread t3 = new MyThread();

        t1.setName("线程1");
        t2.setName("线程2");
        t3.setName("线程3");

        t1.start();
        t2.start();
        t3.start();



    }
}

方式二:实现Runnable接口

public class MyRun implements Runnable{

    @Override
    public void run() {
        //书写线程要执行的代码
        for (int i = 0; i < 100; i++) {
            //获取到当前线程的对象
           
            System.out.println(Thread.currentThread().getName() + "HelloWorld!");
        }
    }
}
public class ThreadDemo {
    public static void main(String[] args) {
        /*
         * 多线程的第二种启动方式:
         *   1.自己定义一个类实现Runnable接口
         *   2.重写里面的run方法
         *   3.创建自己的类的对象
         *   4.创建一个Thread类的对象,并开启线程
         * */


        //创建MyRun的对象
        //表示多线程要执行的任务
        MyRun mr = new MyRun();

        //创建线程对象
        Thread t1 = new Thread(mr);
        Thread t2 = new Thread(mr);

        //给线程设置名字
        t1.setName("线程1");
        t2.setName("线程2");


        //开启线程
        t1.start();
        t2.start();
    }
}
这种方法不能直接使用getName来获取线程的名字,而是先获取当前线程对象,然后再设置线程名

前面两种方法的缺点是?

不能获取多线程执行的执行结果。所以有第三种实现多线程的方法

方式三:实现Callable接口

public class MyCallable implements Callable<Integer> {

    @Override
    public Integer call() throws Exception {
        //求1~100之间的和
        int sum = 0;
        for (int i = 1; i <= 100; i++) {
            sum = sum + i;
        }
        return sum;
    }
}
public class ThreadDemo2 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {


        MyCallable mc = new MyCallable();

        //创建FutureTask对象,用于管理线程运行结果
        FutureTask<Integer> ft = new FutureTask<>(mc);

        Thread t1 = new Thread(ft);

        t1.start();

        //获取多线程执行的结果
        Integer result = ft.get();
        System.out.println(result);
    }
}

三种实现方式的对比

  • 实现Runnable、Callable接口

    • 好处: 扩展性强,实现该接口的同时还可以继承其他的类

    • 缺点: 编程相对复杂,不能直接使用Thread类中的方法

  • 继承Thread类

    • 好处: 编程比较简单,可以直接使用Thread类中的方法

    • 缺点: 可以扩展性较差,不能再继承其他的

常用方法:

StringgetName()

返回此线程的名称。

voidsetName(String name)

将此线程的名称更改为等于参数 name 。

细节:
    1、如果我们没有给线程设置名字,线程也是有默认的名字的
            格式:Thread-X(X序号,从0开始的)
    2、如果我们要给线程设置名字,可以用set方法进行设置,也可以构造方法设置
static ThreadcurrentThread()

返回对当前正在执行的线程对象的引用。

细节:
    当JVM虚拟机启动之后,会自动的启动多条线程
    其中有一条线程就叫做main线程
    它的作用就是去调用main方法,并执行里面的代码
    在以前,我们写的所有的代码,其实都是运行在main线程当中
static voidsleep(long millis, int nanos)

导致正在执行的线程以指定的毫秒数加上指定的纳秒数来暂停(临时停止执行),这取决于系统定时器和调度器的精度和准确性。

 线程休眠。

线程优先级

setPriority()

设置线程优先级,最小是1,最大是10,默认是5

优先级不是绝对的,而是概率问题

public class MyRunnable implements Runnable{

    @Override
    public void run() {
        for (int i = 1; i <= 100; i++) {
            System.out.println(Thread.currentThread().getName() + "---" + i);
        }
    }
}
public class ThreadDemo {
    public static void main(String[] args){
       /*
            setPriority(int newPriority)        设置线程的优先级
            final int getPriority()             获取线程的优先级
       */

        //创建线程要执行的参数对象
        MyRunnable mr = new MyRunnable();
        //创建线程对象
        Thread t1 = new Thread(mr,"飞机");
        Thread t2 = new Thread(mr,"坦克");

        t1.setPriority(1);
        t2.setPriority(10);

        t1.start();
        t2.start();
    }
}

守护线程

setDaemon()

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 < 100; i++) {
            System.out.println(getName() + "---" + i);
        }
    }
}
public class Demo {
    public static void main(String[] args) {
        MyThread1 t1 = new MyThread1();
        MyThread2 t2 = new MyThread2();

        t1.setName("女神");
        t2.setName("备胎");

        //把第二个线程设置为守护线程
        //当普通线程执行完之后,那么守护线程也没有继续运行下去的必要了.
        t2.setDaemon(true);

        t1.start();
        t2.start();
    }
}

出让线程/礼让线程

public class MyThread extends Thread{

    @Override
    public void run() {//"飞机"  "坦克"
        for (int i = 1; i <= 100; i++) {

            System.out.println(getName() + "@" + i);
            //表示出让当前CPU的执行权
            Thread.yield();
        }
    }
}


public class ThreadDemo {
    public static void main(String[] args) {
       /*
            public static void yield()      出让线程/礼让线程

       */

        MyThread t1 = new MyThread();
        MyThread t2 = new MyThread();

        t1.setName("飞机");
        t2.setName("坦克");

        t1.start();
        t2.start();
    }
}

死锁的条件

1、资源有限

2、同步嵌套

线程池

public class MyRunnable implements Runnable{
    @Override
    public void run() {
        for (int i = 1; i <= 100; i++) {
            System.out.println(Thread.currentThread().getName() + "---" + i);
        }
    }
}

public class MyThreadPoolDemo {
    public static void main(String[] args) throws InterruptedException {
    /*
        public static ExecutorService newCachedThreadPool()             创建一个没有上限的线程池
        public static ExecutorService newFixedThreadPool (int nThreads) 创建有上限的线程池
    */


        //1.获取线程池对象
        ExecutorService pool1 = Executors.newFixedThreadPool(3);
        //2.提交任务
        pool1.submit(new MyRunnable());
        pool1.submit(new MyRunnable());
        pool1.submit(new MyRunnable());
        pool1.submit(new MyRunnable());
        pool1.submit(new MyRunnable());
        pool1.submit(new MyRunnable());


        //3.销毁线程池
        //pool1.shutdown();

    }
}

  • 15
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Object-v

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值