线程创建的几种方式

一、线程创建的几种方式

常见的创建线程的方式有一下几种:

  • 继承Thread类
  • 实现Runnable接口
  • 实现Callable接口
  • 线程池创建

个人理解:

a.通过实现Runnable接口创建线程比继承Thread类创建线程好一点,因为每个类只能继承一个父类,但是可以实现多个接口。

b.Callable接口与Runnable接口的区别如下

  1. runnable方式时,多个线程间可以共享实例变量,callable方式则不行

  2. runnable方式没有返回值,callable有返回值

  3. runnable方式run方法的异常只能在内部消化,callable的call()方法允许抛出异常

c.线程并不是却多越好,因为线程的执行要抢占到CPU的执行权才能执行,如果在单核CPU的情况下,使用多线程反而不如单线程快。

d.线程的周期

  • NEW 新建状态,此时线程还没有运行线程中的代码
  • RUNNABLE 就绪状态;处于就绪状态的线程并不一定立即运行run方法,必须还要和其他线程竞争CPU时间
  • RUNNING 运行状态;线程获得CPU时间后才进入运行状态,开始执行run方法
  • BLOCKED 阻塞状态;线程运行过程中会有各种原因来进入阻塞状态,如:调用sleep方法进入休眠;在IO操作中被阻塞;试图得到一个锁,该锁正被其他线程持有;等待某个触发条件.阻塞状态的线程此时没有结束,暂时让出CPU时间给其他线程.
  • DEAD 死亡状态;有两个原因导致线程死亡:第一是run方法正常退出自然死亡;第二是一个未捕获的异常终止了run方法使线程死亡.

为了确定线程在当前是否存活着(就是要么是可运行的,要么是被阻塞了),需要使用isAlive方法,如果是可运行或被阻塞,这个方法返回true;如果线程仍旧是new状态且不是可运行的,或者线程死亡了,则返回false。

二、具体创建方式

1.继承Thread类

package com.xingli.threadDemo;

/**
 *@ClassName MyThead
 *@Description 线程实现的方式第一种:继承thread类
 *@Author William
 *@Date 2019/8/6 11:44
 *@Version 1.0
 */
public class MyTheadTest {
    public static void main(String[] args) {
        //设置线程名字
        Thread.currentThread().setName("主线程:");
        MyThread myThread = new MyThread();
        myThread.setName("子线程:");
        //开启子线程
        myThread.start();
        //主线程
        for(int i = 0;i<5;i++){
            System.out.println(Thread.currentThread().getName() + i);
        }
    }
}
/**
 *@description: 创建MyThread继承Thread类
 * @author: William
 * @date 2019/8/6 11:46
 */
class MyThread extends Thread{
    //重写Thread的run方法
    @Override
    public void run() {
        for (int i = 0; i <5 ; i++) {
            System.out.println(Thread.currentThread().getName()+":"+i);
        }
    }
}

2.实现Runnable接口

package com.xingli.threadDemo;

/**
 *@ClassName MyRunnableTest
 *@Description 多线程实现的第二种方式,实现runnable接口
 *@Author William
 *@Date 2019/8/6 11:51
 *@Version 1.0
 */
public class MyRunnableTest {
    public static void main(String[] args) {
        //设置线程名称
        Thread.currentThread().setName("主线程:");
        Thread t = new Thread(new MyRunnable());
        t.setName("子线程:");
        //开启子线程
        t.start();
        for(int i = 0; i <5;i++){
            System.out.println(Thread.currentThread().getName()+":"+ i);
        }
    }
}

/**
 *@description: 创建MyRunnable实现Runnable接口
 * @author: William
 * @date 2019/8/6 11:52
 */
class MyRunnable implements Runnable {
    //重写run方法
    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println(Thread.currentThread().getName() +":"+ i);
        }
    }
}

3.实现Callable接口

package com.xingli.threadDemo;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

/**
 *@ClassName MyCallableTest
 *@Description 多线程实现的第三种方式,实现callable接口
 *@Author William
 *@Date 2019/8/6 12:03
 *@Version 1.0
 */
public class MyCallableTest {
    public static void main(String[] args) {
        //执行Callable 方式,需要FutureTask 实现实现,用于接收运算结果
        FutureTask<Integer> futureTask = new FutureTask<Integer>(new MyCallable(100));
        new Thread(futureTask).start();
        FutureTask<Integer> futureTask2 = new FutureTask<Integer>(new MyCallable(99));
        new Thread(futureTask2).start();
        //接收线程运算后的结果,这边有一个要注意的地方,FutureTask获取返回值会阻塞主线程,如果获取不到结果主线程下面的方法不会执行
        try {
            Integer sum = futureTask.get();
            System.out.println(sum);
            Integer sum2 = futureTask2.get();
            System.out.println(sum2);
            for (int i = 0; i < 5; i++) {
                System.out.println("主线程结果===");
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
}

/**
 *@description: 创建MyCallable类实现Callable接口
 * @author: William
 * @date 2019/8/6 12:42
 */
class MyCallable implements Callable<Integer> {

    private Integer num ;
    /**
     *@description: 构造方法,让调用方传递一个int类型的数字过来
     * @param num     用户传递数字
     * @author: William
     * @date 2019/8/6 12:08
     */
    public MyCallable(Integer num){
        this.num =num;
    }
    //从写call方法,让方法返回用户传递值%3的结果
    @Override
    public Integer call() throws Exception {
        if(num == null || num<=0){
            return null;
        }
        return num%3;
    }
}

4.线程池创建

package com.xingli.threadDemo;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 *@ClassName MyThreadPoolTest
 *@Description 多线程实现的第三种方式,实现callable接口
 *@Author William
 *@Date 2019/8/6 12:41
 *@Version 1.0
 */
public class MyThreadPoolTest {
    public static void main(String[] args) {
        //创建线程池
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        ThreadPool threadPool = new ThreadPool();
        for(int i =0;i<5;i++){
            //为线程池分配任务
            executorService.submit(threadPool);
        }
        //关闭线程池
        executorService.shutdown();
    }
}

class ThreadPool implements Runnable {
    @Override
    public void run() {
        for(int i = 0 ;i<5;i++){
            System.out.println(Thread.currentThread().getName()+ ":" + i);
        }
    }
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值