美文网首页
线程创建的四种方式+具体案例

线程创建的四种方式+具体案例

作者: 李诗莹__三月 | 来源:发表于2020-03-29 23:21 被阅读0次

    JDK5.0之前

    1、继承于Thread类创建线程

    1.1、继承Thread类创建线程案例

    /**
     * 多线程创建方式一:继承于Thread类
     * 1、创建继承于Thread类的子类
     * 2、重写Thread类的run() ---->在此线程的操作在run()中
     * 3、创建Thread类的子类对象
     * 4、通过此对象调用start()
     * 例子遍历100以内的所有偶数
     */
    class MyThread extends Thread{
        @Override
        public void run() {
            for (int i = 0; i <100 ; i++) {
                if(i%2 == 0){
                    System.out.println(Thread.currentThread().getName()+"***"+i+"******MyThread.start*****");
                }
            }
        }
    }
    public class ThreadTest {
        public static void main(String[] args) {
            //创建Thread的子类对象
            MyThread t1 =  new MyThread();
            //通过此对象调用start():1、启动当前线程 2、调用当前线程的run()
            t1.start();
            //如下操作仍是在main线程中执行
            for (int i = 0; i <100 ; i++) {
                if(i%2 == 0){
                    System.out.println(Thread.currentThread().getName()+i+"*********Main.start*******");
                }
            }
        }
    }
    

    1.2、线程的常用方法

    1、**start(): **启动当前线程 ;调用当前线程的run()

    2、**run(): **通常需要重写Thread类中的此方法,将创建的创建线程需要执行的操作在此方法中声明

    3、currentThread()静态返回执行当前代码的线程,在Thread子类中就是this通常用于主线程和Runnable类实现

    4、getName():获取当前线程的名字

    5、setName():设置当前线程的名字

    6、**yield(): **静态,线程让步。

    • 暂停当前正在执行的线程,把执行机会让给优先级相同或更高的线程
    • 若队列中没有同优先级的线程,忽略此方法

    7、join():当前某个程序执行流中调用其他线程的join()方法时,调用线程将被阻塞,直到join()方法加入的join线程指向完为止

    • 低优先级的线程也可以获得执行

    8、sleep():(指定时间:毫秒):

    • 令当前活动线程在指定时间段内放弃对CPU控制,使其他线程有机会被执行,时间到后重排序
    • 抛出InterruptedException异常

    9、stop(): 强制线程声明期结束,不推荐使用

    10、isAlive(): 返回boolan,判断线程是否还活着

    1.3、线程调度及优先级的概念

    线程调度的策略:

    • 时间片:
    • 抢占式:高优先级的线程抢占CPU

    java的调度方法:

    • 同优先级线程组成先进先出(先到先服务),使用时间片策略
    • 对高优先级,使用优先调度的抢占式策略

    线程的优先级:

    线程优先级等级: MAX_PRORITY:10 MIN_PRORITY:1 MORE_PRORITY:1

    涉及的方法: getPriority():返回线程的优先级 setPriority(int newPriority):改变线程的优先级

    说明:

    线程创建时继承父类线程的优先级

    低优先级只是为获得调度的概率底,并非一定是在高优先级线程之后才被调用

    2、实现Runnable接口创建线程

    2.1、实现Runnable接口创建线程案例

    //创建实现Runnable接口的类
    class MThread implements Runnable {
        @Override
        //实现Runnable中的抽象方法:run()
        public void run() {
            for (int i = 0; i < 100; i++) {
                if (i % 2 == 0) {
                    System.out.println(Thread.currentThread().getName() + "****" + i);
                }
            }
        }
    }
    public class ThreadRuaable {
        public static void main(String[] args) {
            //3、创建类的实例对象
            MThread mt =  new MThread();
            //4、将此对象作为参数传递到Thread类的构造器中,创建Thread类的对象
            Thread thread = new Thread(mt);
            //5、通过Thread类的对象调用start()
            thread.start();
            Thread thread2 = new Thread(mt);
            thread2.start();
    
        }
    }
    
    image.gif

    JDK5.0新增线程创建方式

    1、新增方式一:实现Callable接口:

    1.1、Callable比Runnable的功能更强大:

    1、call()可以有返回值

    2、call()可以抛出异常,被外面的操作捕获,获取异常信息

    3、callable是支持泛型的

    4、需要借助FutureTask类,比如获取返回值

    1.2、Future接口

    • 可以对具体的Runnable、Callable任务的执行结果进行取消、查询是否完成,获取结果等
    • FutureTask是Future接口的唯一的实现类
    • FutureTask同时实现了Runnable,Future接口。它既可以作为Runnable被线程执行,又可以作为Future得到Callable的返回值

    1.3、使用Callable来使用线程计算100以内的偶数的和

    import java.util.concurrent.Callable;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.FutureTask;
    
    //1、创建一个实现Callable的实现类
    class Numbers implements Callable {
        //2、实现call方法,将此线程需要的操作声明在call()方法中
        @Override
        public Object call() throws Exception {
            int sum = 0;
            for (int i = 0; i < 100; i++) {
                if(i % 2 == 0){
                    System.out.println(i);
                    sum += i;
                }
            }
            return sum;
        }
    }
    public class TreadCabble {
        public static void main(String[] args) {
            //3、创建Callable接口的实现类的对象
            Numbers numbers = new Numbers();
            //4、将此Callable接口实现类的对象作为参数传递到FutureTask构造器中,创建FutureTask对象
            FutureTask futureTask = new FutureTask(numbers);
            //5、将FutureTask的对象作为参数传递到Thread类的构造器中,创建Thread对象,并调用start()
            new Thread(futureTask).start();
            try {
                //get()返回值即为FutureTask构造器参数Callable实现类重写的call()的返回值
                Object num = futureTask.get();
                System.out.println(num);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
    }
    
    image.gif

    2、新增方式二:使用线程池

    背景:经常创建和销毁、使用量特别大的资源,比如并发情况下的线程,对性能影响很大。

    思路:提前创建好多个线程,放入线程池中,使用时直接获取,使用完放回池中。可以避免频繁创建和销毁、实现重复利用。类似生活中的公共交通工具

    好处:

    提高影响速度(减少了创建新线程的时间)

    降低资源消耗(重复利用线程池中线程,不需要每次都创建)

    便于线程管理: corePoolSize:核心池的大小 maximunPoolSize:最大线程数 keepAliveTime:线程没有任 务时醉倒保持多长时间后会终止

    线程池相关API

    JDK5.0起提供了线程池相关API:ExecutorServiceExecutors

    ExecutorService:真正的线程池接口。常见子类ThreadPoolExecutor

    Executors:工具类、线程池的工厂类,用于创建并返回不同类型的线程池

    相关文章

      网友评论

          本文标题:线程创建的四种方式+具体案例

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