美文网首页
几种创建线程的方式

几种创建线程的方式

作者: 蜡笔小州 | 来源:发表于2017-12-12 15:46 被阅读15次

继承Thread

通过继承Thread类来创建并启动多线程的一般步骤如下
1】d定义Thread类的子类,并重写该类的run()方法,该方法的方法体就是线程需要完成的任务,run()方法也称为线程执行体。
2】创建Thread子类的实例,也就是创建了线程对象
3】启动线程,即调用线程的start()方法

public class MyThread extends Thread{//继承Thread类

  public void run(){

  //重写run方法

  }

}

public class Main {

  public static void main(String[] args){

    new MyThread().start();//创建并启动线程

  }

}

实现Runnable接口

通过实现Runnable接口创建并启动线程一般步骤如下:
1】定义Runnable接口的实现类,一样要重写run()方法,这个run()方法和Thread中的run()方法一样是线程的执行体
2】创建Runnable实现类的实例,并用这个实例作为Thread的target来创建Thread对象,这个Thread对象才是真正的线程对象
3】第三部依然是通过调用线程对象的start()方法来启动线程

public class MyThread2 implements Runnable {//实现Runnable接口

  public void run(){

  //重写run方法

  }

}

public class Main {

  public static void main(String[] args){

    //创建并启动线程

    MyThread2 myThread=new MyThread2();

    Thread thread=new Thread(myThread);

    thread().start();

    //或者    new Thread(new MyThread2()).start();

  }

}

使用Callable和Future创建线程

和Runnable接口不一样,Callable接口提供了一个call()方法作为线程执行体,call()方法比run()方法功能要强大。
》call()方法可以有返回值
》call()方法可以声明抛出异常
Java5提供了Future接口来代表Callable接口里call()方法的返回值,并且为Future接口提供了一个实现类FutureTask,这个实现类既实现了Future接口,还实现了Runnable接口,因此可以作为Thread类的target。在Future接口里定义了几个公共方法来控制它关联的Callable任务。

boolean cancel(boolean mayInterruptIfRunning):视图取消该Future里面关联的Callable任务

V get():返回Callable里call()方法的返回值,调用这个方法会导致程序阻塞,必须等到子线程结束后才会得到返回值

V get(long timeout,TimeUnit unit):返回Callable里call()方法的返回值,最多阻塞timeout时间,经过指定时间没有返回抛出TimeoutException

boolean isDone():若Callable任务完成,返回True

boolean isCancelled():如果在Callable任务正常完成前被取消,返回True
介绍了相关的概念之后,创建并启动有返回值的线程的步骤如下:
1】创建Callable接口的实现类,并实现call()方法,然后创建该实现类的实例(从java8开始可以直接使用Lambda表达式创建Callable对象)。
2】使用FutureTask类来包装Callable对象,该FutureTask对象封装了Callable对象的call()方法的返回值
3】使用FutureTask对象作为Thread对象的target创建并启动线程(因为FutureTask实现了Runnable接口)
4】调用FutureTask对象的get()方法来获得子线程执行结束后的返回值

public class CallableThreadTest implements Callable<Integer> {
    @Override
    public Integer call() throws Exception {
        int i = 0;
        for (; i < 100; i++) {
            Thread.sleep(300);
            Log.i("zhou", Thread.currentThread().getName() + " " + i); //4.执行线程
        }
        return i;
    }
}
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        CallableThreadTest ctt = new CallableThreadTest(); //1.类实现callable接口 实现call为方法体
        FutureTask<Integer> ft = new FutureTask<>(ctt); //2.用futruetask包装
        for (int i = 0; i < 100; i++) {
            Log.i("zhou", Thread.currentThread().getName() + " 的循环变量i的值" + i);
            if (i == 20) {
                new Thread(ft, "有返回值的线程").start(); //3.new Thread传入这个futruetask对象实现线程 启动
            }
        }
        Log.i("zhou","~~~~~~~~~~~~~~~~~~~~~~~~~~~");
        try {
            Log.i("zhou", "子线程的返回值:" + ft.get()); //5.线程的返回结果会在线程执行完毕后返回 没执行完没返回 且会阻塞下面的代码
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        Log.i("zhou","!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); //6.在5没执行的话6无法执行! 会造成anr 

    }
}

这里返回值如果在主线程获取的话,会阻塞代码,甚至anr。
AsyncTask内部就是使用的futureTask,FutureTask在高并发环境下确保任务只执行一次,所以多次excute会异常也与这个有关系。

线程池

线程的提供的四种方式,或者工厂方法创建。

ThreadFactory

public class FixCountThreadFactory implements ThreadFactory{  
    private final int MAX_THREAD;  
      
    private final AtomicInteger count = new AtomicInteger(0);  
      
    public FixCountThreadFactory(int maxThread) {  
        MAX_THREAD = maxThread;  
    }  
      
    @Override  
    public Thread newThread(Runnable r) {  
        int incrementAndGet = count.incrementAndGet();  
        if(incrementAndGet > MAX_THREAD)  
        {  
            count.decrementAndGet();  
            return null;  
        }  
          
        return new Thread(r);  
    }  
}  

通常实现ThreadFactory接口的newThread方法,用工厂模式。
比如给线程命名。

相关文章

  • 线程

    java 中创建线程有哪几种方式? Java中创建线程主要有三种方式: 一、继承Thread类创建线程类 (1)定...

  • 创建线程几种方式

    1、继承Thread类 2、实现Runnable接口 推荐:可实现多个接口,而只能继承一个类。 3、应用程序可以使...

  • Future系列(FutureTask)

    一、前言 创建线程有几种方式? 继承 Thread 类 实现 Runnable 接口 但这两种方式创建的线程是属于...

  • Java多线程:线程的创建与启动

    # 面试题: Java中创建线程有几种方式。 不同的创建方式有什么区别。 如何启动一个线程。 # Java中创建线...

  • 线程的几种创建方式

    线程的几种创建方式 编写多线程程序是为了实现多任务的并发执行,从而能够更好地与用户交互。一般有三种方法,Threa...

  • 创建线程的几种方式

    说道线程,肯定会想到使用 java.lang.Thread.java这个类那么创建线程也主要有2种方式第一种方式:...

  • 几种创建线程的方式

    继承Thread 通过继承Thread类来创建并启动多线程的一般步骤如下1】d定义Thread类的子类,并重写该类...

  • 创建线程的几种方式

    1.通过继承Thread类创建线程类 1.步骤 定义Thread类的子类FirstThread,并重写run()方...

  • 创建线程的几种方式

    创建多线程是为了实现多任务并发执行,从而能够更好地与用户交互,达到更高的效率。 创建线程常用的方式有四种:1、继承...

  • 创建线程的几种方式

    继承Thread类 实现Runnable接口 通过Callable创建线程(异步,可以返回结果) 线程池创建

网友评论

      本文标题:几种创建线程的方式

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