zoukankan      html  css  js  c++  java
  • 实现线程的方式:Thread类重写run();Runnable类重写run();Callable类重写call();实现线程的方式

    实现线程的方式

    1.继承Thread类重写run();

    Thread类中常用的两个构造方法是:
        public Thread();//无参构造
        public Thread(String threadName);//有参构造
    
    完成线程真正功能的代码放在类的run()方法中,当一个类继承Thread类后,就可以在该类中覆盖run()方法,
    将实现该功能的代码写入run()方法中,然后调用Thread类中的start()方法执行线程,等价于调用run()方法;
    其中,Thread类不可以重复启动一个线程,也就是说,不可以调用已经启动的线程。强行调用,会抛出异常IllegalTreadStateException。

    2.实现Runnable接口重写run();

    实际上,Thread类实现了Runnable接口,其中的run()方法就是对Runnable接口中的run()方法的具体实现。
    实现Runnable接口的程序会创建一个Thread对象,并将Runnable对象和Thread对象相关联。适合多个相同的程序代码的线程去处理同一个资源。

    Thread类有以下两个构造方法:使用这两个方法就可以将Runnable和Thread两个实例相关联。
      public Thread(Runnable target);/traget是目标的意思
      public Thread(Runnable target,String name);

    使用Runnable接口启动线程的步骤:
      建立Runnable对象;
      使用参数为Runnable对象的构造方法创建Thread实例;
      调用start()方法启动线程;
    说到这里你可能也不明白怎么整,所以,请看下面的代码:
    RET.java
    package com;
    
    public class RET implements Runnable {
    
        private static int ticket = 10;
        public RET() {
    
        }
    
        @Override
        public void run() {//防止线程抢占资源
            while(ticket>0) {
                synchronized("") {//这样也行,定义锁也行,目前我还没发现这两种的区别,待定!!!!
                    if(ticket>0) {
                        System.out.println(Thread.currentThread().getName()+"卖出第"+ticket+"张票");
                        --ticket;
                    }else {
                        System.out.println("票卖完了");
                    }
                }
            }
        }
    }

    App.java

    package com;
    
    public class App {
    
        public App() {
            RET r1 = new RET();
            RET r2 = new RET();
            
            new Thread(r1).start();
            new Thread(r2).start();
            new Thread(r2).start();//可以调用已经启动的线程,虽然可以这样,但是这条线程算是第三条线程了。不过不建议这样用,因为很混乱。
        }
        public static void main(String[] args) {
            new App();
        }
    }
    其中,如果一个类继承Thread,就不可以资源共享。但是如果实现了Runable接口的话,就可以实现资源共享。说到共享资源,就一定会抢占资源!要加锁!
    而且,无论是继承Thread还是实现Runnable都不可以给方法加锁eg:public synchronized void run() {//防止线程抢占资源 因为这样加锁顶不住!!
    都要static Object lock="locked";//这样加锁!!!!在改变数据的时候要synchronized(lock){在这里改变数据}!!!!

    3.实现Callable接口重写call();

    Callable接口实际上是属于Executor框架中的功能类,Callable接口与Runnable接口的功能类似,但提供了比Runnable更加强大的功能。

      Callable可以在任务结束的时候提供一个返回值,Runnable无法提供这个功能

      Callable的call方法分可以抛出异常,而Runnable的run方法不能抛出异常。

    步骤:

      自定义一个类实现java.util.concurrent包下的Callable接口
      重写call方法
      将要在线程中执行的代码编写在call方法中
      创建ExecutorService线程池
      将自定义类的对象放入线程池里面
      获取线程的返回结果
      关闭线程池,不再接收新的线程,未执行完的线程不会被关闭

    看代码:

    call.java

    package com;
    
    import java.util.concurrent.Callable;
    
    public class call implements Callable<String> {//定义一个类实现Callable<V>接口
        private static int ticket = 10;
        private Object lock = "";
        public call() {
            
        }
    
        @Override
        public String call() throws Exception {
            while(ticket>0) {
                synchronized (lock) {
                    System.out.println(Thread.currentThread().getName()+"第"+ticket+"张");
                    --ticket;
                }
            }
            return "没错,我执行完了上面的代码,还告诉你我完事了。";
        }
    
    }

    App.java

    package com;
    
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.Future;
    
    public class App {
    
        public App() {
            //创建ExecutorService线程池
            ExecutorService threadPool = Executors.newSingleThreadExecutor();
            //创建存储Future对象,用来存放ExecutorService的执行结果
            Future<String> future = threadPool.submit(new call());
            try {
                System.out.println("等待线程结束");
                System.out.println(future.get());
            } catch (Exception e) {
                e.printStackTrace();
            }finally{
           threadPool.shutdown();

        }
      } 
      public static void main(String[] args) {
        
    new App();
      }
    }


    但是,线程池怎么可能只放一个线程呢??请看多个线程的办法,就是存到了数组里

    cable.java
    package com;
    
    import java.util.concurrent.Callable;
    
    public class cable implements Callable<String> {//定义一个类实现Callable<V>接口
        private  int a,b;
        public cable(int a,int b) {
            this.a=a;
            this.b=b;
        }
    
        @Override
        public String call() throws Exception {
            System.out.println(a+b+" "+Thread.currentThread().getName());
            Thread.sleep(1000);
            return "没错,我执行完了上面的代码,还告诉你我完事了。";
        }
    
    }
    App.java
    package com;
    
    import java.util.ArrayList;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.Future;
    
    
    public class App {
    
        public App() throws InterruptedException, ExecutionException {
            //创建ExecutorService线程池
            ExecutorService threadPool = Executors.newSingleThreadExecutor();
            //创建存储Future对象的集合,用来存放ExecutorService的执行结果
             ArrayList<Future<String>> future = new ArrayList<Future<String>>();
            //举例子:开3个线程,将返回的Future对象放入集合中
            future.add(threadPool.submit(new cable(1,2)));
            future.add(threadPool.submit(new cable(4,5)));
            future.add(threadPool.submit(new cable(7,8)));
            
            for (Future<String> fs : future) {
                //判断线程是否执行结束,如果执行结束就将结果打印
                if (fs.isDone()) {
                    System.out.println("22222"+fs.get());
                } else {
                    System.out.println("44444"+fs.toString());
                }
            }
            //关闭线程池,不再接收新的线程,未执行完的线程不会被关闭
            threadPool.shutdown();
            System.out.println("main方法执行结束");
        }
        public static void main(String[] args) throws InterruptedException, ExecutionException {
            new App();
        }
    }
  • 相关阅读:
    重新安装AD RMS
    Exp00009错误解決
    AD RMS 问题解决 事件ID:139
    如何破解微软的正版增值烦恼
    如何批量更改帐号的属性
    ORA31694,原来是文件有问题
    Standby异常解决
    ASP.NET 常用网站
    .NET C#读取Excel内容
    AD Usre lastLogon Time
  • 原文地址:https://www.cnblogs.com/cattree/p/10659634.html
Copyright © 2011-2022 走看看