创建线程的四种方法
创建线程的四种方法
-
继承Thread类创建线程
- 写一个Thread的子类去继承Thread
- 复写run方法,方法内写线程执行的代码
- 创建Thread的子类对象
- 调用start方法,开启线程
-
实现runable接口的方法
- 写一个Runnable接口的实现类
- 复写run方法,编写线程的执行代码
- 创建Thread对象,将Runnable接口的实现类对象作为参数传递给Thread
- 调用start方法,开启线程
-
实现Callable接口的方法
- 写一个Callable接口的实现类
- 复写一个call方法。有返回值
- 创建Callable的实现类对象
- 创建一个FutureTask对象,把Callable的子类作为参数传递
- 创建Thread对象,把Futrure对象作为参数传递
- 调用start方法,开启线程
package com.my.springbootdemo; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; public class MyThread implements Callable<String> { private int count = 20; @Override public String call() throws Exception { for (int i = count; i > 0; i--) { // Thread.yield(); System.out.println(Thread.currentThread().getName()+" is " + i); } return "sale out"; } public static void main(String[] args) throws InterruptedException, ExecutionException { Callable<String> callable =new MyThread(); //启动三个线程的话需要写三个futureTask,不然只会随机启动一个 FutureTask <String>futureTask1=new FutureTask<>(callable); FutureTask <String>futureTask2=new FutureTask<>(callable); FutureTask <String>futureTask3=new FutureTask<>(callable); Thread mThread1=new Thread(futureTask1); Thread mThread2=new Thread(futureTask2); Thread mThread3=new Thread(futureTask3); mThread1.setName("t1"); mThread2.setName("t2"); mThread3.setName("t3"); mThread1.start(); mThread2.start(); mThread3.start(); System.out.println(futureTask1.get()); } }
-
使用线程池启动线程
- 创建Excutor工具类创建三种常量池对象
- 调用submit方法,并传递新建的Runnable方法
- 停止常量池,调用shutdown方法
package com.my.springbootdemo; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class Test { public static void main(String[] args) { //使用固定大小线程池 ExecutorService ex=Executors.newFixedThreadPool(5); for(int i=0;i<5;i++) { ex.submit(new Runnable() { @Override public void run() { for(int j=0;j<10;j++) { System.out.println(Thread.currentThread().getName() + " j " + j); } } }); } ex.shutdown(); //使用单线程池 ExecutorService ex=Executors.newSingleThreadExecutor(); for(int i=0;i<5;i++) { ex.submit(new Runnable() { @Override public void run() { for(int j=0;j<10;j++) { System.out.println(Thread.currentThread().getName()+j); } } }); } ex.shutdown(); //使用缓存线程池 ExecutorService ex=Executors.newCachedThreadPool(); for(int i=0;i<5;i++) { ex.submit(new Runnable() { @Override public void run() { for(int j=0;j<10;j++) { System.out.println(Thread.currentThread().getName()+j); } } }); } ex.shutdown(); } }
拓展
StringBuffer和StringBuilder作用:
因为String类型的内容是不可变的,如果一直需要append字符串或者其他操作,而中间的值都是无意义的,浪费大量内存,而StringBuffer和StringBuilder就是解决这个问题,当修改或追加字符串时,不会生成新的字符串,而是在原来的对象进行修改,不用分配大量的空间给临时对象了。
两者区别
-
两者的方法作用是相同的。
-
StringBuffer是线程安全的,实现的时候会有大量的代码来处理同步,如果程序只是单线程的,会大大的降低效率。
-
StringBuilder是不考虑线程安全的,执行效率也快,适合单线程程序。
ThreadLocal
ThreadLocal并不是一个Thread,而是Thread的局部变量。
ThreadLocal是JDK包提供的,它提供线程本地变量,如果创建一个ThreadLocal变量,那么访问这个变量的每个线程都会有这个变量的一个副本,在实际多线程操作的时候,操作的是自己本地内存中的变量,从而规避了线程安全问题。
作用:
解决线程安全,它通过为每个线程提供一个独立的变量副本解决了变量并发访问的冲突问题,在很多情况下,ThreadLocal比直接使用synchronized同步机制解决线程安全问题更简单,其结果程序拥有更高的并发性。
版权声明:
本站所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自
郭远的博客空间!
喜欢就支持一下吧
打赏
微信
支付宝