zoukankan      html  css  js  c++  java
  • 多线程,,,,,线程池

                                多线程

    1.      Thread类

    创建新执行线程有两种方法。

    l  一种方法是将类声明为 Thread 的子类。该子类应重写 Thread 类的 run 方法。创建对象,开启线程。run方法相当于其他线程的main方法。

    l  另一种方法是声明一个实现 Runnable 接口的类。该类然后实现 run 方法。然后创建Runnable的子类对象,传入到某个线程的构造方法中,开启线程。

    继承Thread,重写run方法

    public class MyThread extends Thread{
    
    public void run() {
        
        //重写,描述线程任务
        for(int i=0;i<100;i++){
            System.out.println("MyThread:"+i);
        }
    }
    }

    测试

    public class Demo02 {//多线程程序同时进行
    public static void main(String[] args) {
        //创建线程对象
        MyThread my=new MyThread();
        my.start();//开启线程,start调用的是Thread类中的run方法
        for(int i=0;i<100;i++){
            System.out.println("main:"+i);
        }
    }
    }

    两个循环同时进行,交叉打印,因为调start方法时会开一个新栈,两个栈交替执行

        获取线程名称

    l  Thread.currentThread()获取当前线程对象

    l  Thread.currentThread().getName();获取当前线程对象的名称

    public class Demo02 {//多线程程序同时进行
    public static void main(String[] args) {
        //创建线程对象
        MyThread my=new MyThread();
        
        my.start();//开启线程
        for(int i=0;i<100;i++){
            //先获得线程对象,再获取线程名称
            System.out.println(Thread.currentThread().getName()+":"+i);
        }
    }
    }
    public class MyThread extends Thread{
    
    public void run() {
        
        //重写,描述线程任务
        for(int i=0;i<100;i++){
            System.out.println(Thread.currentThread().getName()+":"+i);//获取线程名称
        }
    }
    }

          创建线程方式—实现Runnable接口

    Runnable接口用来指定每个线程要执行的任务。包含了一个 run 的无参数抽象方法,需要由接口实现类重写该方法。

    l  Thread类构造方法

    创建线程的步骤。

    1、定义类实现Runnable接口。

    2、覆盖接口中的run方法。。

    3、创建Thread类的对象

    4、将Runnable接口的子类对象作为参数传递给Thread类的构造函数。

    5、调用Thread类的start方法开启线程。

    public class Demo01 {
    public static void main(String[] args) {
        //创建线程执行目标对象
        MyRunnable my=new MyRunnable();
        //将Runnable接口的子类对象作为参数传递给Thread类的构造函数
        Thread th=new Thread(my);
        //开启线程
        th.start();
        //主线程任务
        for(int i=0;i<100;i++){
            System.out.println(Thread.currentThread().getName()+":"+i);
        }
    }
    }
    public class MyRunnable implements Runnable {
        //定义线程要执行的run方法逻辑
        public void run() {
            for(int i=0;i<100;i++){
                System.out.println(Thread.currentThread().getName()+":"+i);
            }
        }
    
    
    }

        实现Runnable的原理

    实现Runnable接口,避免了继承Thread类的单继承局限性。覆盖Runnable接口中的run方法,将线程任务代码定义到run方法中。

    创建Thread类的对象,只有创建Thread类的对象才可以创建线程。线程任务已被封装到Runnable接口的run方法中,而这个run方法所属于Runnable接口的子类对象,所以将这个子类对象作为参数传递给Thread的构造函数,这样,线程对象创建时就可以明确要运行的线程的任务。

        实现Runnable的好处

    现Runnable接口避免了单继承的局限性,所以较为常用。实现Runnable接口的方式,更加的符合面向对象,线程分为两部分,一部分线程对象,一部分线程任务。

         线程的匿名内部类使用

    匿名内部类格式:new父类或接口(){     重写父类方法    }

    使用线程的内匿名内部类方式,可以方便的实现每个线程执行不同的线程任务操作。

    public class Demo02 {
    public static void main(String[] args) {
        //继承Thread类的匿名内部类对象
        //new父类(){重写父类方法}
        Thread t=new Thread(){//多态,得到父类的子类对象
            public void run() {
                for(int i=1;i<10;i++){
                    System.out.println(Thread.currentThread().getName()+":"+i);
                }
            }
            };
            t.start();
            //实现runable接口
            //创建线程任务对象
            Runnable my=new Runnable(){
                public void run() {
                    for(int i=0;i<10;i++){
                        System.out.println(Thread.currentThread().getName()+":::"+i);
                    }
                };
            };
            //创建线程对象,交替运行
            new Thread(my).start();
        }
    }

        线程池

          线程池概念

    线程池,其实就是一个容纳多个线程的容器,其中的线程可以反复使用,省去了频繁创建线程对象的操作,无需反复创建线程而消耗过多资源。

          使用线程池方式--Runnable接口

    l  Executors:线程池创建工厂类

      public static ExecutorService newFixedThreadPool(int nThreads):返回线程池对象

    l  ExecutorService:线程池类

      Future<?> submit(Runnable task):获取线程池中的某一个线程对象,并执行

    l  Future接口:用来记录线程任务执行完毕后产生的结果。线程池创建与使用

     

    l  使用线程池中线程对象的步骤:

      创建线程池对象

      创建Runnable接口子类对象

      提交Runnable接口子类对象

      关闭线程池

    public class Demo03 {
    public static void main(String[] args) {
        //获取线程池对象
        ExecutorService es=Executors.newFixedThreadPool(2);
        //创建线程任务对象
        MyRunnable r=new MyRunnable();
        //执行线程任务,如果线程任务大于线程数,就排队执行
        es.submit(r);
        es.submit(r);
        //销毁线程池
        es.shutdown();
    }
    }

    l  Runnable接口实现类

    public class MyRunnable implements Runnable {
        //定义线程要执行的run方法逻辑
        public void run() {
            for(int i=0;i<100;i++){
                System.out.println(Thread.currentThread().getName()+":"+i);
            }
        }
    
    
    }

          使用线程池方式—Callable接口

    l  Callable接口:与Runnable接口功能相似,用来指定线程的任务。其中的call()方法,用来返回线程任务执行完毕后的结果,call方法可抛出异常。

    l  ExecutorService:线程池类

      <T> Future<T> submit(Callable<T> task):获取线程池中的某一个线程对象,并执行线程中的call()方法

    l  Future接口:用来记录线程任务执行完毕后产生的结果。线程池创建与使用

     

    l  使用线程池中线程对象的步骤:

      创建线程池对象

      创建Callable接口子类对象

      提交Callable接口子类对象

      关闭线程池

    public class Demo04 {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        //创建线程池对象
        ExecutorService es=Executors.newFixedThreadPool(2);
        //创建Callable对象
        MyCallable c=new MyCallable();
        //执行线程任务
        //从线程池中获取线程对象,然后调用MyRunnable中的run()
        Future<String> f=es.submit(c);
        //注意:submit方法调用结束后,程序并不终止,
        //是因为线程池控制了线程的关闭。将使用完的线程又归还到了线程池中
        //获取返回值
        String mes=f.get();
        System.out.println(mes);
        es.shutdown();
    }
    }

    l  Callable接口实现类,call方法可抛出异常、返回线程任务执行完毕后的结果

    public class MyCallable implements Callable<String>{
    
        
        public String call() throws Exception {
            
            return "abc";
        }
    
    }

    练习

    用两条线程分别计算1-50的和 和1-100的和,将结果返回

    public class Demo01 {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        //用两条线程分别计算1-50的和 和1-100的和,将结果返回
        //获取线程池对象
        ExecutorService es=Executors.newFixedThreadPool(2);
        //创建线程任务
        Call c1=new Call(100);
        Call c2=new Call(50);
        //执行
        Future<Integer> f1=es.submit(c1);
        Future<Integer> f2=es.submit(c2);
        //获取返回值
        System.out.println(f1.get());
        System.out.println(f2.get());
        //销毁线程池
        es.shutdown();
        
        
    }
    }
    public class Call implements Callable<Integer>{
        private int num;
        public Call(int num){
            this.num=num;
        }
        public Integer call() throws Exception {
            int sum=0;
            for(int i=1;i<=num;i++){
                sum=sum+i;
            }
            return sum;
        }
    
    }
  • 相关阅读:
    Mysql查询数据库表结构以及字段类型并展示
    Configutation读取properties文件信息
    通过淘宝接口免费获取IP地址信息
    SpringMVC+SPring+Maven+Mybaits+Shiro+Mybaits基础开发项目
    【微信开发】【Asp.net MVC】-- 微信分享功能
    NPOI导出多张图片到Excel
    年末回想 ---- 小步快跑
    【吉光片羽】短信验证
    【JavaScript吉光片羽】--- 滑动条
    电子书和纸质书有什么区别
  • 原文地址:https://www.cnblogs.com/111wdh/p/13425012.html
Copyright © 2011-2022 走看看