最新消息: USBMI致力于为网友们分享Windows、安卓、IOS等主流手机系统相关的资讯以及评测、同时提供相关教程、应用、软件下载等服务。

线程创建的四种方法

互联网 admin 4浏览 0评论

线程创建的四种方法

线程创建的四种方法:

创建线程的常用四种方法:

第一种   继承Thread类

第二种  实现Runnable接口

第三种  实现Callable接口

第四种  通过线程池如用Executor框架


创建线程的常用四种方法:

  1.  继承Thread类
  2. 实现Runnable接口
  3. 实现Callable接口
  4. 线程池方法创建如用Executor框架

        通过继承Thread类或者Runnable接口、Callable接口都可以实现多线程,不过实现Runnable接口与实现Callable接口的方式基本相同,只是Callable接口里定义的方法有返回值,可以声明抛出异常而已。

 采用实现Runnable、Callable接口的方式创建线程的优缺点:

    优点:线程类只是实现了Runnable或者Callable接口,还可以继承其他类。这种方式下,多个线程可以共享一个target对象,所以非常适合多个相同线程来处理同一份资源的情况,从而可以将CPU、代码和数据分开,形成清晰的模型,较好的体现了面向对象的思想。

    缺点:编程稍微复杂一些,如果需要当我当前该线程,则必须使用Thread.currentThread()方法

采用继承Thread类的方法创建线程的优缺点:

     优点:编写简单,如果需要访问当前线程,则无需使用Thread.currentThread()方法,直接使用this即可获取当前线程

     缺点:因为线程类已经继承了Thread类,Java语言是单继承的,所以不能再继承其他父类。

采用线程池创建线程的优点:

      1、提高响应速度----减少了创建新线程的时间

      2、降低资源消耗----重复利用线程池中线程,不需要每次都创建

      3、便于线程管理

第一种   继承Thread类

通过继承Thread类来创建并启动多线程的一般步骤如下

1、定义Thread类的子类,并重写该类的run()方法,该方法的方法体就是线程需要完成的任务,run()方法也称为线程执行体。

2、创建Thread子类的实例,也就是创建了线程对象

3、启动线程,即调用线程的start()方法

//1. 创建一个继承于Thread类的子类
class MyThread extends Thread{// 2. 重写Tread类的run()@Overridepublic void run() {for (int i = 0; i <100 ; i++) {if(i%2==0){// System.out.println(i);//输出线程名System.out.println(Thread.currentThread().getName()+":"+i);}}}
}
public class ThreadTest {public static void main(String[] args) {//3. 创建Tread类的子类的对象MyThread t = new MyThread();//4. 通过此对象调用start(): A :启动当前线程    B: 调用当前线程的run()方法t.start();// 第一个问题:  这是调方法 还是在主线程中执行的  我们不能直接调用run()的方式启动线程// t.run();//第二个问题:再启动一个线程 不可以让已经start()了的线程去执行 不然会报错IllegalThreadStateException//  t.start();MyThread t2 = new MyThread();t2.start();// 证明线程有交互性for (int j = 0; j < 50; j++) {if(j%2!=0){System.out.println(Thread.currentThread().getName()+":"+j+"*****");}}//创建Thread类的匿名子类的方式new Thread(){@Overridepublic void run() {for (int k = 0; k <10 ; k++) {System.out.println(Thread.currentThread().getName()+": LP");}}}.start();}
}

运行部分截图:

第二种  实现Runnable接口

通过实现Runnable接口创建并启动线程一般步骤如下:

1、定义Runnable接口的实现类,一样要重写run()方法,这个run()方法和Thread中的run()方法一样是线程的执行体

2、创建Runnable实现类的实例,并用这个实例作为Thread的target来创建Thread对象,这个Thread对象才是真正的线程对象

3、第三部依然是通过调用线程对象的start()方法来启动线程

// 1、创建一个类实现Runnable接口
class Number implements Runnable{// 2. 重写Runnable接口的run()@Overridepublic void run() {for (int i = 0; i <100 ; i++) {if(i%2==0){// System.out.println(i);//输出线程名System.out.println(Thread.currentThread().getName()+":"+i);}}}
}
public class ThreadRunnable {public static void main(String[] args) {// 3、创建实现Runnable接口类的对象Number number=new Number();// 4、将对象作为Thread类的参数Thread thread=new Thread(number,"线程1");thread.start();}
}

运行结果部分截图:

第三种  实现Callable接口

1、创建Callable接口的实现类,并实现call()方法,然后创建该实现类的实例(从java8开始可以直接使用Lambda表达式创建Callable对象)。

2、使用FutureTask类来包装Callable对象,该FutureTask对象封装了Callable对象的call()方法的返回值

3、使用FutureTask对象作为Thread对象的target创建并启动线程(因为FutureTask实现了Runnable接口)

4、调用FutureTask对象的get()方法来获得子线程执行结束后的返回值

class cal implements Callable{private int num=0;@Overridepublic Integer call() throws Exception {for (int i = 0; i <100 ; i++) {if(i%2==0){// System.out.println(i);//输出线程名System.out.println(Thread.currentThread().getName()+":"+i);num+=i;}}return num;}
}public class CallableThread {public static void main(String[] args) throws ExecutionException, InterruptedException {// 将接口Callable实现类的对象作为FutureTask的参数FutureTask futureTask=new FutureTask(new cal());// 将FutureTask对象作为Thread的参数new Thread(futureTask, "窗口1").start();// 还可以获取Callable中call方法的返回值System.out.println("num的值:"+futureTask.get());}
}

运行结果部分截图:

第四种  通过线程池如用Executor框架

        1.5后引入的Executor框架的最大优点是把任务的提交和执行解耦。要执行任务的人只需把Task描述清楚,然后提交即可。这个Task是怎么被执行的,被谁执行的,什么时候执行的,提交的人就不用关心了。具体点讲,提交一个Callable对象给ExecutorService(如最常用的线程池ThreadPoolExecutor),将得到一个Future对象,调用Future对象的get方法等待执行结果就好了。Executor框架的内部使用了线程池机制,它在java.util.cocurrent 包下,通过该框架来控制线程的启动、执行和关闭,可以简化并发编程的操作。因此,在Java 5之后,通过Executor来启动线程比使用Thread的start方法更好,除了更易管理,效率更好(用线程池实现,节约开销)外,还有关键的一点:有助于避免this逃逸问题——如果我们在构造器中启动一个线程,因为另一个任务可能会在构造器结束之前开始执行,此时可能会访问到初始化了一半的对象用Executor在构造器中。


/** 1、继承Thread类创建线程*  1) 定义Thread类的子类,并重写该类的run()方法,该方法的方法体就是线程需要完成的任务,run方法也称为线程执行体。*  2) 创建Thread子类的实例,也就是创建了线程对象*  3) 启动线程,调用线程的start()方法*/
class MyThread1 extends Thread{@Overridepublic void run() {// 重写run方法System.out.println(Thread.currentThread().getName()+"你开始拉屎?...\t"+new Date());try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"你结束拉屎?...\t"+new Date());}
}/** 2、实现Runnable接口创建线程*  1) 定义Runnable接口的实现类,一样要重写run()方法,这个run()方法和Thread中的run()方法一样是线程的执行体*  2) 创建Runnable实现类的实例,并用这个实例作为Thread的target来创建Thread对象,这个Thread对象才是真正的线程对象*  3) 第三步依然是通过调用线程对象的start()方法来启动线程*/
class MyThread2 implements Runnable{@Overridepublic void run() {// 重写run方法System.out.println(Thread.currentThread().getName()+"你开始吃饭?...\t"+new Date());try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"你结束吃饭?...\t"+new Date());}
}/** 3、实现Callable接口创建线程**/
class MyThread3 implements Callable {private Integer sum=0;@Overridepublic Integer call() throws Exception {for(int i=0;i<=100;i++){Thread.sleep(100);System.out.println(Thread.currentThread().getName()+"--->"+i);sum+=i;}return sum;}
}
public class ThreadPool {public static void main(String[] args) {// 1、提供指定的线程数量的线程池ExecutorService executorService= Executors.newFixedThreadPool(10);//        ThreadPoolExecutor service=(ThreadPoolExecutor) executorService;
//        // 设置线程池的属性
//        service.setCorePoolSize(15);executorService.execute(new MyThread1()); // 执行Runnable接口的实现类executorService.execute(new MyThread2()); // 执行Runnable接口的实现类Future submit = executorService.submit(new MyThread3());// 执行Callable接口的实现列try {System.out.println(submit.get());} catch (InterruptedException e) {e.printStackTrace();} catch (ExecutionException e) {e.printStackTrace();}
// 关闭线程executorService.shutdown();}
}

 运行结果部分截图:

线程创建的四种方法

线程创建的四种方法:

创建线程的常用四种方法:

第一种   继承Thread类

第二种  实现Runnable接口

第三种  实现Callable接口

第四种  通过线程池如用Executor框架


创建线程的常用四种方法:

  1.  继承Thread类
  2. 实现Runnable接口
  3. 实现Callable接口
  4. 线程池方法创建如用Executor框架

        通过继承Thread类或者Runnable接口、Callable接口都可以实现多线程,不过实现Runnable接口与实现Callable接口的方式基本相同,只是Callable接口里定义的方法有返回值,可以声明抛出异常而已。

 采用实现Runnable、Callable接口的方式创建线程的优缺点:

    优点:线程类只是实现了Runnable或者Callable接口,还可以继承其他类。这种方式下,多个线程可以共享一个target对象,所以非常适合多个相同线程来处理同一份资源的情况,从而可以将CPU、代码和数据分开,形成清晰的模型,较好的体现了面向对象的思想。

    缺点:编程稍微复杂一些,如果需要当我当前该线程,则必须使用Thread.currentThread()方法

采用继承Thread类的方法创建线程的优缺点:

     优点:编写简单,如果需要访问当前线程,则无需使用Thread.currentThread()方法,直接使用this即可获取当前线程

     缺点:因为线程类已经继承了Thread类,Java语言是单继承的,所以不能再继承其他父类。

采用线程池创建线程的优点:

      1、提高响应速度----减少了创建新线程的时间

      2、降低资源消耗----重复利用线程池中线程,不需要每次都创建

      3、便于线程管理

第一种   继承Thread类

通过继承Thread类来创建并启动多线程的一般步骤如下

1、定义Thread类的子类,并重写该类的run()方法,该方法的方法体就是线程需要完成的任务,run()方法也称为线程执行体。

2、创建Thread子类的实例,也就是创建了线程对象

3、启动线程,即调用线程的start()方法

//1. 创建一个继承于Thread类的子类
class MyThread extends Thread{// 2. 重写Tread类的run()@Overridepublic void run() {for (int i = 0; i <100 ; i++) {if(i%2==0){// System.out.println(i);//输出线程名System.out.println(Thread.currentThread().getName()+":"+i);}}}
}
public class ThreadTest {public static void main(String[] args) {//3. 创建Tread类的子类的对象MyThread t = new MyThread();//4. 通过此对象调用start(): A :启动当前线程    B: 调用当前线程的run()方法t.start();// 第一个问题:  这是调方法 还是在主线程中执行的  我们不能直接调用run()的方式启动线程// t.run();//第二个问题:再启动一个线程 不可以让已经start()了的线程去执行 不然会报错IllegalThreadStateException//  t.start();MyThread t2 = new MyThread();t2.start();// 证明线程有交互性for (int j = 0; j < 50; j++) {if(j%2!=0){System.out.println(Thread.currentThread().getName()+":"+j+"*****");}}//创建Thread类的匿名子类的方式new Thread(){@Overridepublic void run() {for (int k = 0; k <10 ; k++) {System.out.println(Thread.currentThread().getName()+": LP");}}}.start();}
}

运行部分截图:

第二种  实现Runnable接口

通过实现Runnable接口创建并启动线程一般步骤如下:

1、定义Runnable接口的实现类,一样要重写run()方法,这个run()方法和Thread中的run()方法一样是线程的执行体

2、创建Runnable实现类的实例,并用这个实例作为Thread的target来创建Thread对象,这个Thread对象才是真正的线程对象

3、第三部依然是通过调用线程对象的start()方法来启动线程

// 1、创建一个类实现Runnable接口
class Number implements Runnable{// 2. 重写Runnable接口的run()@Overridepublic void run() {for (int i = 0; i <100 ; i++) {if(i%2==0){// System.out.println(i);//输出线程名System.out.println(Thread.currentThread().getName()+":"+i);}}}
}
public class ThreadRunnable {public static void main(String[] args) {// 3、创建实现Runnable接口类的对象Number number=new Number();// 4、将对象作为Thread类的参数Thread thread=new Thread(number,"线程1");thread.start();}
}

运行结果部分截图:

第三种  实现Callable接口

1、创建Callable接口的实现类,并实现call()方法,然后创建该实现类的实例(从java8开始可以直接使用Lambda表达式创建Callable对象)。

2、使用FutureTask类来包装Callable对象,该FutureTask对象封装了Callable对象的call()方法的返回值

3、使用FutureTask对象作为Thread对象的target创建并启动线程(因为FutureTask实现了Runnable接口)

4、调用FutureTask对象的get()方法来获得子线程执行结束后的返回值

class cal implements Callable{private int num=0;@Overridepublic Integer call() throws Exception {for (int i = 0; i <100 ; i++) {if(i%2==0){// System.out.println(i);//输出线程名System.out.println(Thread.currentThread().getName()+":"+i);num+=i;}}return num;}
}public class CallableThread {public static void main(String[] args) throws ExecutionException, InterruptedException {// 将接口Callable实现类的对象作为FutureTask的参数FutureTask futureTask=new FutureTask(new cal());// 将FutureTask对象作为Thread的参数new Thread(futureTask, "窗口1").start();// 还可以获取Callable中call方法的返回值System.out.println("num的值:"+futureTask.get());}
}

运行结果部分截图:

第四种  通过线程池如用Executor框架

        1.5后引入的Executor框架的最大优点是把任务的提交和执行解耦。要执行任务的人只需把Task描述清楚,然后提交即可。这个Task是怎么被执行的,被谁执行的,什么时候执行的,提交的人就不用关心了。具体点讲,提交一个Callable对象给ExecutorService(如最常用的线程池ThreadPoolExecutor),将得到一个Future对象,调用Future对象的get方法等待执行结果就好了。Executor框架的内部使用了线程池机制,它在java.util.cocurrent 包下,通过该框架来控制线程的启动、执行和关闭,可以简化并发编程的操作。因此,在Java 5之后,通过Executor来启动线程比使用Thread的start方法更好,除了更易管理,效率更好(用线程池实现,节约开销)外,还有关键的一点:有助于避免this逃逸问题——如果我们在构造器中启动一个线程,因为另一个任务可能会在构造器结束之前开始执行,此时可能会访问到初始化了一半的对象用Executor在构造器中。


/** 1、继承Thread类创建线程*  1) 定义Thread类的子类,并重写该类的run()方法,该方法的方法体就是线程需要完成的任务,run方法也称为线程执行体。*  2) 创建Thread子类的实例,也就是创建了线程对象*  3) 启动线程,调用线程的start()方法*/
class MyThread1 extends Thread{@Overridepublic void run() {// 重写run方法System.out.println(Thread.currentThread().getName()+"你开始拉屎?...\t"+new Date());try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"你结束拉屎?...\t"+new Date());}
}/** 2、实现Runnable接口创建线程*  1) 定义Runnable接口的实现类,一样要重写run()方法,这个run()方法和Thread中的run()方法一样是线程的执行体*  2) 创建Runnable实现类的实例,并用这个实例作为Thread的target来创建Thread对象,这个Thread对象才是真正的线程对象*  3) 第三步依然是通过调用线程对象的start()方法来启动线程*/
class MyThread2 implements Runnable{@Overridepublic void run() {// 重写run方法System.out.println(Thread.currentThread().getName()+"你开始吃饭?...\t"+new Date());try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"你结束吃饭?...\t"+new Date());}
}/** 3、实现Callable接口创建线程**/
class MyThread3 implements Callable {private Integer sum=0;@Overridepublic Integer call() throws Exception {for(int i=0;i<=100;i++){Thread.sleep(100);System.out.println(Thread.currentThread().getName()+"--->"+i);sum+=i;}return sum;}
}
public class ThreadPool {public static void main(String[] args) {// 1、提供指定的线程数量的线程池ExecutorService executorService= Executors.newFixedThreadPool(10);//        ThreadPoolExecutor service=(ThreadPoolExecutor) executorService;
//        // 设置线程池的属性
//        service.setCorePoolSize(15);executorService.execute(new MyThread1()); // 执行Runnable接口的实现类executorService.execute(new MyThread2()); // 执行Runnable接口的实现类Future submit = executorService.submit(new MyThread3());// 执行Callable接口的实现列try {System.out.println(submit.get());} catch (InterruptedException e) {e.printStackTrace();} catch (ExecutionException e) {e.printStackTrace();}
// 关闭线程executorService.shutdown();}
}

 运行结果部分截图:

与本文相关的文章

发布评论

评论列表 (0)

  1. 暂无评论