zoukankan      html  css  js  c++  java
  • 线程的创建和使用

    线程的创建

    方式一:创建继承Thread类的子类,需要重写父类的run()方法,然后创建子类的对象,通过子类对象调用start()方法(包括采用匿名子类)。

     小案例:

    package com.threadstudy;
    
    public class MultiThreadingTest1 {
        public static void main(String[] args) {
            MyThread1 myThread = new MyThread1();
            myThread.start();
            //如果直接调用run方法不属于多线程,因为没有开启新线程
            //myThread.run();
            //同一个新线程的对象不能重复start启动,如想重新启动新线程,需要创建一个新的对象
            //myThread.start();//运行报错:java.lang.IllegalThreadStateException
            System.out.println("我是主线程");
    
            //匿名子类写法创建多线程
            new Thread() {
                @Override
                public void run() {
                    // 此线程执行需要执行的操作声明在run中
                    int sum = 0;
                    for (int i = 0; i <= 100; i++) {
                        sum += i;
                    }
                    System.out.println("我是匿名子类新线程");
                }
            }.start();
            //main方法中可以同时创建多个匿名子类线程
            //.......
        }
    }
    class MyThread1 extends Thread {
        @Override
        public void run() {
            // 此线程执行需要执行的操作声明在run中
            int sum = 0;
            for (int i = 0; i <= 100; i++) {
                sum += i;
            }
            System.out.println("我是新线程");
        }
    }
    

      

    运行结果:

    我是主线程

    我是新线程

    我是匿名子类新线程

    方式二:创建实现Runnable的类,实现Runnable中的抽象方法run(),创建类的对象,将此对象传入Thread类的构造器中创建Thread类的对象,调用Thread类的对象的start()方法(包括匿名写法)。

    小案例:

    package com.threadstudy;
    
    /**
     * 创建多线程的方式二:实现Runnable接口
     * 1.创建一个实现了Runnable接口的类
     * 2.实现类去实现Runnable中的抽象方法:run()
     * 3.创建实现类的对象
     * 4.将此对象作为参数传递到Thread类的构造器中,创建Thread类的对象
     * 5.通过Thread类的对象调用start()
     */
    public class MultiTheadingTest2 {
        public static void main(String[] args) {
            MyThread2 myThread2 = new MyThread2();
            Thread thread = new Thread(myThread2);
            thread.start();
            System.out.println("我是主线程");
            //匿名写法
            new Thread(
                    new Runnable() {
                        public void run() {
                            // 此线程执行需要执行的操作声明在run中
                            int sum = 0;
                            for (int i = 0; i <= 100; i++) {
                                sum += i;
                            }
                            System.out.println("我是匿名新线程");
                        }
                    }).start();
        }
    
    }
    
    class MyThread2 implements Runnable {
    
        public void run() {
            // 此线程执行需要执行的操作声明在run中
            int sum = 0;
            for (int i = 0; i <= 100; i++) {
                sum += i;
            }
            System.out.println("我是新线程");
        }
    }
    

      

    方式三:JDK5.0新特性。实现Callable接口。需要借助Future接口的唯一实现类FutureTask辅助线程的对象创建和返回值获取(FutureTask还实现了Runnable接口),再创建Thread对象,将FutureTask类的对象作为构造器参数传入,完成线程的创建,最后调用start()方法完成线程启动。

    小案例:

    package com.threadstudy;
    
    import java.util.concurrent.Callable;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.FutureTask;
    
    public class MultiThreadTest3 {
        public static void main(String[] args) {
            MyThread3 myThread3 = new MyThread3();
            FutureTask futureTask = new FutureTask(myThread3);
            Thread thread = new Thread(futureTask);
            thread.start();
    
            try {
                Object sum = futureTask.get();
                //System.out.println(sum);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
            System.out.println("我是主线程");
    
            // 匿名写法
            new Thread(new FutureTask(new Callable() {
    
                public Object call() throws Exception {
                    // 此线程执行需要执行的操作声明在call中
                    int sum = 0;
                    for (int i = 0; i <= 100; i++) {
                        sum += i;
                    }
                    System.out.println("我是匿名新线程");
                    return sum;// int类型赋值给Object,自动装箱
                }
            }) ).start();
        }
    }
    
    class MyThread3 implements Callable {
    
        public Object call() throws Exception {
            // 此线程执行需要执行的操作声明在call中
            int sum = 0;
            for (int i = 0; i <= 100; i++) {
                sum += i;
            }
            System.out.println("我是新线程");
            return sum;// int类型赋值给Object,自动装箱
        }
    }
    

      

    运行结果:

    我是新线程

    我是主线程

    我是匿名新线程

    方式四:JDK5.0新特性。使用线程池,提前创建好多个线程放入线程池中,使用时直接获取,使用完放回线程池中。可以做到提高响应速度(减少线程创建的时间)和降低资源消耗(可重复利用线程)。利用Executors工具类创建线程池,然后提供Runnable(excute())或Callable(submit())接口的实现类的对象,执行指定线程的操作。最后,关闭线程池shutdown()。

    小案例:

    package com.threadstudy;
    
    import java.util.concurrent.Callable;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    public class MultiThreadTest4 {
        public static void main(String[] args) {
            // 利用工具类Executors创建线程池
            ExecutorService threadPool = Executors.newFixedThreadPool(10);
            threadPool.submit(new MyThread4());// 适用于实现Callable接口的线程
            threadPool.execute(new MyThread5());// 适用于实现Runnable接口的线程
            threadPool.shutdown();
        }
    }
    
    class MyThread4 implements Callable {
    
        public Object call() throws Exception {
            // 此线程执行需要执行的操作声明在call中
            int sum = 0;
            for (int i = 0; i <= 100; i++) {
                sum += i;
            }
            System.out.println("我是CALL新线程");
            return sum;
        }
    
    }
    
    class MyThread5 implements Runnable {
    
        public void run() {
            // 此线程执行需要执行的操作声明在call中
            int sum = 0;
            for (int i = 0; i <= 100; i++) {
                sum += i;
            }
            System.out.println("我是RUN新线程");
        }
    
    }
    

      

    运行结果:

    我是CALL新线程

    我是RUN新线程

    创建线程方式间的比较

    JDK5.0前两种方式的比较(继承Thread类与实现Runnable接口)

    • 继承方式的弊端:单继承约束下线程只能继承于Thread类,不能继承于其他的类
    • 实现方式的优势:天然存在共享数据的情况,不需要将共享的数据设置为静态使用static修饰
    • Thread类实际上是Runnable接口的实现类

    实现Runnable接口和Callable接口方式的比较

    • Runnable接口实现方法需要重写run(),但是run()方法没有返回值,Callable接口实现方式重写Call()方法,可以有返回值;
    • Runnable接口实现方法不能抛出异常,只能try-catch捕获异常,Callable接口实现方式可以throws抛出异常;
    • Runnable接口实现方法不支持泛型,Callable接口实现方式支持泛型;
    • Callable接口实现方式返回值需要借助FutureTask类获取返回值。

    线程的常用方法

    • 1.start():启动当前线程,自动调用run()方法;
    • 2.run():通常需要子类重写,并将新线程需要执行的操作声明在run()方法中;
    • 3.currentThread():静态方法,返回当前执行的线程的对象(返回对象类型为Thread);
    • 4.getName():获取当前线程的名称,不设置名称情况下,默认调用Thread的空参构造器Thread-0等等(线程名不等于类名);
    • 5.setName():设置当前线程的名称,Thread.currentThread.setName("")或者 对象名.setName("")
    • 6.yield():静态方法,线程让步,释放当前CPU的执行,可以让多个线程同时竞争资源;
    • 7.join():在线程A中调用线程B的join()方法,相当于让线程B直接插入线程A方法中运行(线程A阻塞),直至线程B结束,继续线程A;
    • 8.stop():强制结束线程的生命周期不推荐使用(Deprecated);
    • 9.sleep(long millis):静态方法,毫秒单位,睡眠一段时间之后重新加入CPU资源竞争,睡眠的时候仍然握锁;
    • 10.isAlive():判断当前线程是否存活。
  • 相关阅读:
    【洛谷 4613】Olivander
    【洛谷 1385】密令
    【洛谷 4439】Aron
    【洛谷 3383】线性筛素数
    【洛谷 2412】查单词
    【洛谷 1980】计数问题
    【洛谷 3372】(模板)线段树 1
    Luogu P3743 kotori的设备
    Luogu P2340 [USACO03FALL]Cow Exhibition G
    Luogu P3047 [USACO12FEB]Nearby Cows G
  • 原文地址:https://www.cnblogs.com/dongyaotou/p/14391368.html
Copyright © 2011-2022 走看看