前言:多线程下程序运行的结果是随机的,以下案例代码的运行结果仅供参考

一 通过继承Thread线程创建的方法与执行的步骤

/*
1 继承Thread 2重写run方法 3创建线程继承类的子类
4 调用start(一个线程只能通过调用一次start来进行启动)*/
class MyThread extends Thread{public MyThread(String name){//调用Thread类中的构造方法才能顺序初始化成功线程名super(name);}@Overridepublic void run() {for (int i = 0; i < 3; i++) {//线程名(默认):Thread-0,currentThread是获取当前的线程System.out.println(Thread.currentThread().getName() + i);}}
}public class ThreadTest {/*当前主线程是main线程,我们在此又开了个名为myThread的线程,main线程与thread线程的执行时顺序是随机的由于myThread的启动和被分配cpu时间片都需要时间,所以通常是main线程先执行只有start才能启动一个线程,启动后需要抢占cpu资源,抢占成功才能执行线程中的run方法,如果直接调用线程的run方法相当于在主线程main中正常的调用一个对象myThread的run方法若没有手动设置线程名称时,会自动分配一个线程的名称,如线程对象myThread会被自动分配线程名称Thread-0设置线程名称是为了区分当前正在执行的线程是哪一个线程,所以在设置线程名称时应避免重复!*/public static void main(String[] args) throws InterruptedException {MyThread myThread = new MyThread("myThread");//start方法是由新建态=> 就绪态。有两步①启动线程②调用线程的run方法myThread.start();System.out.println("========以下是main线程的执行步骤========");for (int i = 0; i < 3; i++) {System.out.println(Thread.currentThread().getName()+":"+i);}}
}


二 通过实现Runnble的方法

/*
①创建一个Runnable的实现类②实现类去重写接口的run方法③创建实现类的对象
④将该对象作为参数传入到Thread构造器来构造一个Thread类型的对象⑤通过该thread对象调用时start*/
class MyRun implements Runnable{@Overridepublic void run() {for (int i = 0; i < 3; i++) {//线程名(默认):Thread-0,currentThread是获取当前的线程System.out.println(Thread.currentThread().getName() + i);}}
}public class ThreadTest {public static void main(String[] args) throws InterruptedException {Thread thread = new Thread(new MyRun());thread.setName("mythread");thread.start();System.out.println("========以下是main线程的执行步骤========");for (int i = 0; i < 3; i++) {System.out.println(Thread.currentThread().getName()+":"+i);}}
}

三、实现Callable的方式
方法三比方法二好,原因①call方法可以有返回值 ②Callable支持泛型③call可以声明抛出异常信息而run中不能

/*
相比较Runable接口,call()方法新增捕获和抛出异常和返回值的功能,实现步骤如下:
①创建一个Callable的实现类并重写call方法,将线程需要执行的任务写到call方法中
②实例化一个该实现类的对象callable
③将callable作为参数构造一个FutureTask的对象ftt
④将ftt作为参数(Runnable接口类型的引用target)构造Thread对象thread
⑤thread.start()启动线程
补充:call的返回值类型即为Callable的泛型类型,通过ftt.get()可以返回call方法的返回值*/
class MyCall implements Callable<Integer>{@Overridepublic Integer call() throws Exception {for (int i = 0; i < 3; i++) {System.out.println(Thread.currentThread().getName() +  ":" +i);}return 1;}
}public class ThreadTest {public static void main(String[] args) throws InterruptedException, ExecutionException {Callable<Integer> callable = new MyCall();FutureTask<Integer> ftt = new FutureTask<Integer>(callable);Thread thread = new Thread(ftt);thread.start();System.out.println(ftt.get());}
}


四、通过线程池的方式
由于线程的创建与销毁都是很耗费资源的工作,在高并发的情况下对性能影响非常大,解决:可以提前创建多个线程放入线程池,使用的时不是现造而是去线程池中取,使用完不是销毁而是重新放回线程池,避免频繁的创建于销毁,实现重复利用,类似于公交车,优势非常明显,降低响应时间(节约了创建线程的时间)节约系统资源(重复利用线程池的线程减少了创建和销毁线程的频率)提高系统系统,利于管理(例如可以通过参数指定线程池大小,池内最大线程数,线程保持时间)

class MyRun implements Runnable{@Overridepublic void run() {System.out.println("这是MyRun");}
}class MyCall implements Callable{@Overridepublic Object call() throws Exception {return 1;}
}
/*
1 创建一个指定线程数量的线程池对象service
2 将service强转为ThreadPoolExecutor以便设置线程池的属性
3 需要传入Runnable或Callable接口实现类的对象(匿名对象)作为参数执行指定的线程的操作
4 关闭连接池
*/public class ThreadTest {public static void main(String[] args) throws InterruptedException, ExecutionException {//1 创建一个指定线程数量的线程池对象serviceExecutorService service = Executors.newFixedThreadPool(10);//2 将service强转为ThreadPoolExecutor以便设置线程池的属性ThreadPoolExecutor executor = (ThreadPoolExecutor)service;//3 需要传入Runnable或Callable接口实现类的对象(匿名对象)作为参数执行指定的线程的操作service.execute(new MyRun());service.submit(new MyCall());//4 关闭连接池service.shutdown();}
}

推荐学习:线程的安全问题与三种解决方法

java线程三种创建方式与线程池的应用相关推荐

  1. 多线程—Thread类及线程三种创建方式及对比

    线程创建的3种方法: 1.继承Thread类并重写run方法 Thread类方法: Thread Thread.currentThread() :获得当前线程的引用.获得当前线程后对其进行操作. Th ...

  2. Java数组—三种创建方式与区别

    Java创建数组有三种方式 1. 第一种方式 int arr [ ]  = new int [5] ; 属于动态创建,声明并创建内存空间,等待赋值. //创建数组的第一种方式 //属于动态创建,声明并 ...

  3. java线程的任务的三种创建方式,严格地说,就一种,就是如何重写Runnable接口的run()方法

    仅简单演示Java中线程任务的三种创建方式 第一种:使用了适配器模式,有返回值,能抛出异常,任务代码写在Callable.call()方法中,Runnable的run方法会通过适配器调用到Callab ...

  4. 线程的三种创建方式以及代码实现

    线程和进程的概念 一个进程可以有多个线程 程序:是指令和数据的有序集合(静态的) 进程:是执行程序的一次执行过程(动态的),是系统资源分配的单位.在操作系统中运行的程序就是进程. 通常在一个进程中可以 ...

  5. 线程的三种创建方式和他们的优缺点

    文章目录 一.线程的三种创建方式 1.继承Thread 2.实现Runable接口 3.实现Callable接口 二.三种创建方式的优缺点 1.使用Runnable接口比使用继承Thread的优势 2 ...

  6. JavaScript 闭包的详细分享(三种创建方式)(附小实例)

    JavaScript闭包的详细理解 一.原理:闭包函数--指有权访问私有函数里面的变量和对象还有方法等:通俗的讲就是突破私有函数的作用域,让函数外面能够使用函数里面的变量及方法. 1.第一种创建方式 ...

  7. Web框架之Django_07 进阶操作(MTV与MVC、多对多表三种创建方式、前后端传输数据编码格式contentType、ajax、自定义分页器)

    阅读目录 一.MVC与MTV 二.多对多表的创建 三.ajax,前后端传输编码格式contentType 四.批量插入数据与自定义分页器 摘要 MTV与MVC 多对多表三种创建方式 ajax ,前后端 ...

  8. Django09:图书管理系统笔记/choices用法/ MTV与MVC模型/多对多三种创建方式

    图书管理系统笔记 redirect括号内可以直接写url 也可以直接写别名 但如果别名需要参数,必须使用reverse解析. choices用法 使用场景:能列举完全的数据 #使用方法:xxx_cho ...

  9. Servlet 的三种创建方式

    Servlet 创建有三种方式. 1.实现 Servlet 接口 因为是实现 Servlet 接口,所以我们需要实现接口里的方法. 下面我们也说明了 Servlet 的执行过程,也就是 Servlet ...

最新文章

  1. kubernetes关键特性和概述
  2. json的序列化与反序列化
  3. C 格式化的输入输出(printf scanf)
  4. 【MySQL】MySQL5.6新特性之Index Condition Pushdown
  5. matlab out of memory产生原因和解决办法
  6. C语言合并排序实例代码
  7. invalid currency could not be saved in AG3
  8. 计算机入门与学习回忆(一)
  9. LeetCode 1942. 最小未被占据椅子的编号(set)
  10. java 多线程同步_详解Java多线程编程中的线程同步方法
  11. 快速排序算法理解-python
  12. 强迫症告辞!三星Galaxy S11这“凌乱”的后置5摄,感受下
  13. python和c++哪个好-c语言和python哪个好入门?
  14. 云原生:云计算时代命题之终极解决方案
  15. Java开发笔记(一百四十七)通过JDBC管理数据库
  16. delphi2007 打开项目时,突然报错,提示microsoft.net borland 报错
  17. 计算机专业的八字,生辰八字五行计算器
  18. 线上幽灵:世界头号黑客米特尼克自传
  19. 论软件架构建模技术与应用
  20. 【Shell】Sed 删除、替换、增加字符串

热门文章

  1. c#中queue的用法
  2. Vue.set()详解
  3. [HTTP] Nginx代理以及面向未来的HTTP
  4. 夯实基础,彻底掌握js的核心技术(四):ES5、ES6对象方法详解
  5. css3实现背景渐变的方法
  6. PyTorch入门(二)--实现简单神经网络
  7. 【CV实战】Ubuntu18.04源码编译安装opencv-3.4.X+测试demo
  8. mysql获取当前时间的订单_mysql获取当前时间,及其相关操作
  9. 剑指offer-JZ82 二叉树中和为某一值的路径(一)(附区分DFS和回溯)
  10. ASP.NET Core 入门教程 8、ASP.NET Core + Entity Framework Core 数据访问入门