美文网首页
线程创建得方式

线程创建得方式

作者: 码农小钰 | 来源:发表于2020-07-09 14:11 被阅读0次

    线程的创建有
    1.继承thread类
    继承Thread类创建线程的步骤为:
      (1)创建一个类继承Thread类,重写run()方法,将所要完成的任务代码写进run()方法中;
    (2)创建Thread类的子类的对象;
    (3)调用该对象的start()方法,该start()方法表示先开启线程,然后调用run()方法;

    public class Thread1 {
         
        public static void main(String[] args) {
             
            Thread.currentThread().setName("主线程");
            System.out.println(Thread.currentThread().getName()+":"+"输出的结果");
            //创建一个新线程
            ThreadDemo1 thread1 = new ThreadDemo1();
            //为线程设置名称
            thread1.setName("线程一");
            //开启线程
            thread1.start();
        }
    }
     
    class ThreadDemo1 extends Thread{
         
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName()+":"+"输出的结果");
        }
         
    }
    

    2.runnable接口
    (1)创建一个类并实现Runnable接口
    (2)重写run()方法,将所要完成的任务代码写进run()方法中
    (3)创建实现Runnable接口的类的对象,将该对象当做Thread类的构造方法中的参数传进去
    (4)使用Thread类的构造方法创建一个对象,并调用start()方法即可运行该线程

    public class Thread2 {
         
        public static void main(String[] args) {
            Thread.currentThread().setName("主线程");
            System.out.println(Thread.currentThread().getName()+":"+"输出的结果");
            //创建一个新线程
            Thread thread2 = new Thread(new ThreadDemo2());
            //为线程设置名称
            thread2.setName("线程二");
            //开启线程
            thread2.start();
        }
         
    }
     
    class ThreadDemo2 implements Runnable {
     
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName()+":"+"输出的结果");
        }
         
    }
    

    3.使用callable
    callable是一个函数式接口,因此可以用作lambda表达式或方法引用的赋值对象。


    image.png

    callable与runnable两者创建线程得对比

     创建新类MyThread实现runnable接口
    class MyThread implements Runnable{
     @Override
     public void run() {
     
     }
    }
    新类MyThread2实现callable接口
    class MyThread2 implements Callable<Integer>{
     @Override
     public Integer call() throws Exception {
      return 200;
     } 
    }
     面试题:callable接口与runnable接口的区别?
     
     答    (1)是否有返回值
           (2)是否抛异常
           (3)落地方法不一样,一个是run,一个是call
    

    那callable可以直接替代runnable吗?答案是不可以,因为Thread中没有callable得构造方法.看javaAPI文档


    image.png

    4.线程池
    (1)使用Executors类中的newFixedThreadPool(int num)方法创建一个线程数量为num的线程池
    (2)调用线程池中的execute()方法执行由实现Runnable接口创建的线程;调用submit()方法执行由实现Callable接口创建的线程
    (3)调用线程池中的shutdown()方法关闭线程池

    public class Thread4 {
         
        public static void main(String[] args) throws Exception {
             
            Thread.currentThread().setName("主线程");
            System.out.println(Thread.currentThread().getName()+":"+"输出的结果");
            //通过线程池工厂创建线程数量为2的线程池
            ExecutorService service = Executors.newFixedThreadPool(2);
            //执行线程,execute()适用于实现Runnable接口创建的线程
            service.execute(new ThreadDemo4());
            service.execute(new ThreadDemo6());
            service.execute(new ThreadDemo7());
            //submit()适用于实现Callable接口创建的线程
            Future<String> task = service.submit(new ThreadDemo5());
            //获取call()方法的返回值
            String result = task.get();
            System.out.println(result);
            //关闭线程池
            service.shutdown();
        }
    }
    //实现Runnable接口
    class ThreadDemo4 implements Runnable{
         
        @Override
        public void run() {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+":"+"输出的结果");
        }
         
    }
    //实现Callable接口
    class ThreadDemo5 implements Callable<String>{
     
        @Override
        public String call() throws Exception {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+":"+"输出的结果");
            return Thread.currentThread().getName()+":"+"返回的结果";
        }
     
    }
    //实现Runnable接口
    class ThreadDemo6 implements Runnable{
         
        @Override
        public void run() {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+":"+"输出的结果");
        }
         
    }
    //实现Runnable接口
    class ThreadDemo7 implements Runnable{
         
        @Override
        public void run() {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+":"+"输出的结果");
        }
         
    }
    

    最后在说说FutureTask,首先FutureTask是什么,举一个例子

    例子:
    (1)老师上着课,口渴了,去买水不合适,讲课线程继续,我可以单起个线程找班长帮忙买水,
    水买回来了放桌上,我需要的时候再去get。
    (2)4个同学,A算1+20,B算21+30,C算31*到40,D算41+50,是不是C的计算量有点大啊,
    FutureTask单起个线程给C计算,我先汇总ABD,最后等C计算完了再汇总C,拿到最终结果
    (3)高考:会做的先做,不会的放在后面做
    
    image.png

    在主线程中需要执行比较耗时的操作时,但又不想阻塞主线程时,可以把这些作业交给Future对象在后台完成,
    当主线程将来需要时,就可以通过Future对象获得后台作业的计算结果或者执行状态。
    一般FutureTask多用于耗时的计算,主线程可以在完成自己的任务后,再去获取结果。
    仅在计算完成时才能检索结果;如果计算尚未完成,则阻塞 get 方法。一旦计算完成,
    就不能再重新开始或取消计算。get方法而获取结果只有在计算完成时获取,否则会一直阻塞直到任务转入完成状态,
    然后会返回结果或者抛出异常。
    只计算一次
    get方法放到最后

    最后通过代码来实现FutureTask.

    import java.util.concurrent.Callable;
    import java.util.concurrent.FutureTask;
    import java.util.concurrent.TimeUnit;
    
    class MyThread implements Runnable{
    
        @Override
        public void run() {
    
        }
    }
    class MyThread2 implements Callable<Integer>{
    
        @Override
        public Integer call() throws Exception {
            System.out.println(Thread.currentThread().getName()+"come in callable");
            return 200;
        }
    }
    
    
    public class CallableDemo {
    
    
        public static void main(String[] args) throws Exception {
    
            //FutureTask<Integer> futureTask = new FutureTask(new MyThread2());
            FutureTask<Integer> futureTask = new FutureTask(()->{
                System.out.println(Thread.currentThread().getName()+"  come in callable");
                TimeUnit.SECONDS.sleep(4);
                return 1024;
            });
            FutureTask<Integer> futureTask2 = new FutureTask(()->{
                System.out.println(Thread.currentThread().getName()+"  come in callable");
                TimeUnit.SECONDS.sleep(4);
                return 2048;
            });
    
            new Thread(futureTask,"zhang3").start();
            new Thread(futureTask2,"li4").start();
    
            //System.out.println(futureTask.get());
            //System.out.println(futureTask2.get());
            //1、一般放在程序后面,直接获取结果
            //2、只会计算结果一次
    
            while(!futureTask.isDone()){
                System.out.println("***wait");
            }
            System.out.println(futureTask.get());
            System.out.println(Thread.currentThread().getName()+" come over");
        }
    }
    

    注:对于futureTask我也还有未弄懂得,学习过后再补上

    相关文章

      网友评论

          本文标题:线程创建得方式

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