0
点赞
收藏
分享

微信扫一扫

java并发原理实战(4) -- 线程的创建方式


文章目录

  • ​​创建线程​​
  • ​​1.继承thread​​
  • ​​2.实现runnable接口:​​
  • ​​3.匿名内部类的方式:​​
  • ​​①重写thead类+匿名内部类​​
  • ​​②实现runnable+匿名内部类​​
  • ​​③实现runnable+重写thead类+匿名内部类​​
  • ​​4.创建既有返回值和异常的线程​​
  • ​​5.定时器​​
  • ​​timer​​
  • ​​5.线程池​​
  • ​​6. spring的多线程方式​​
  • ​​7.使用lambd表达式​​

创建线程

java并发原理实战(4) -- 线程的创建方式_匿名内部类

1.继承thread

执行流程:

​客户端调用start()方法----private native void start0();---控制权交给jvm ----抢到资源后,执行该线程父类自定义过的自己又去重写的run()方法​

实例代码:

public class Demo1 extends Thread {
public Demo1(String name) {
super(name);
}
@Override
public void run() {
while(!interrupted()){
System.out.println(getName()+ " 线程执行了....");
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) throws InterruptedException {
Demo1 demo1 = new Demo1("线程1");
demo1.start();
}
}

运行结果:

java并发原理实战(4) -- 线程的创建方式_ide_02

2.实现runnable接口:

执行流程:

​作为线程任务存在:线程所要做的功能 相当于给线程和任务分类,让代码更解耦 thread---new thread(target) --init方法将全局的target赋值传递过来当前线程任务---jvm 调用 ---target.run方法​

java并发原理实战(4) -- 线程的创建方式_线程池_03

英文翻译:

  • 1.如果此线程是使用单独的​​Runnable​​​ 运行对象构造的,则将调用​​Runnable​​​对象的​​run​​方法; *否则,此方法不执行任何操作并返回。
  • 2.·Thread `的子类应重写此方法.

这里就是第1种情况,调用我们传递的runable对象的run方法。

实例代码:

public class Demo2 implements Runnable{
@Override
public void run() {
while(true){
System.out.println("thread running ...");
}
}

public static void main(String[] args) {
Thread thread = new Thread(new Demo2());
thread.start();

}
}

运行结果:

java并发原理实战(4) -- 线程的创建方式_线程池_04

3.匿名内部类的方式:

本质:只有一个线程的情况,实例不用给名字了,直接new完再用,其实也是结果上面两种方式的执行。

①重写thead类+匿名内部类

public static void main(String[] args) {
//如果只有一个线程的话,可以使用匿名内部类
//使用匿名内部类,相当于线程子类
new Thread(){
@Override
public void run() {
System.out.println("thread start1....");
}
}.start();
}

②实现runnable+匿名内部类

//把线程任务作为参数传递
new Thread(new Runnable(){
@Override
public void run() {
System.out.println("thread start2....");
}
}).start();

③实现runnable+重写thead类+匿名内部类

可以这么写,但是平时不怎么干。

//把线程任务作为参数传递
new Thread(new Runnable(){
@Override
public void run() {
System.out.println("thread start2....");
}
}){
@Override
public void run() {
System.out.println("thread start1....");
}
}.start();

运行结果: thread start1…

为啥尼?

这里涉及到了jvm中的方法调用动态分派的知识:也就是方法重写的原理。

实现了runable接口,作为线程任务参数传递进去,但是jvm会在执行时调用子类的run,和自己这个类的run方法没关系了,即使有target也不会被执行。

4.创建既有返回值和异常的线程

原理是啥先不用管,后面在补充吧,代码演示如下:

public class Demo4  implements Callable<Integer> {
@Override
public Integer call() throws Exception {
System.out.println("正在进行进行紧张的计算");
Thread.sleep(3000);
return 1;
}

public static void main(String[] args) throws ExecutionException, InterruptedException {
//作为执行的任务
Demo4 demo4 = new Demo4();
//封装
FutureTask<Integer> task = new FutureTask<>(demo4);
//包装到thread类
Thread thread = new Thread(task);
thread.start();
System.out.println("我先干点别的");
//拿到结果
Integer result = task.get();
System.out.println(result);
}
}

运行结果:

java并发原理实战(4) -- 线程的创建方式_ide_06

运行了线程,还返回了值,牛。

5.定时器

timer

看下他的api:

java并发原理实战(4) -- 线程的创建方式_ide_07


java并发原理实战(4) -- 线程的创建方式_线程池_08


代码演示:

public class Demo5 {
public static void main(String[] args) {
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("timetask is run");
}
},0,1000);
}
}

运行结果:

java并发原理实战(4) -- 线程的创建方式_ide_09

缺点:

当一个Timer 运行多个TimerTask 时,只要其中一个TimerTask 在执行中向run 方法
外抛出了异常,则其他任务也会自动终止。

5.线程池

java并发原理实战(4) -- 线程的创建方式_线程池_10

public class Demo6 {
public static void main(String[] args) {
//10个线程的线程池
ExecutorService threadPool = Executors.newFixedThreadPool(10);
for (int i=0;i<100;i++){
//创建线程任务
threadPool.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
});
}
//停掉线程池
threadPool.shutdown();
}
}

运行结果:

java并发原理实战(4) -- 线程的创建方式_ide_11


演示2:

public class Demo6 {
public static void main(String[] args) {
//自动创建线程池的大小,不够用就创建,用完就回收。
ExecutorService threadPool = Executors.newCachedThreadPool();
for (int i=0;i<100;i++){
//创建线程任务
threadPool.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
});
}
//停掉线程池
threadPool.shutdown();
}
}

java并发原理实战(4) -- 线程的创建方式_匿名内部类_12

6. spring的多线程方式

pom

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.2.RELEASE</version>
</dependency>

Config

@Configurable
@ComponentScan("com.hfl.demo.liquidbasedemo.quartz")
@EnableAsync
public class Config implements AsyncConfigurer {
@Override
public Executor getAsyncExecutor() {//实现AsyncConfigurer接口并重写getAsyncExecutor方法,并返回一个ThreadPoolTaskExecutor,这样我们就获得了一个基于线程池TaskExecutor
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
taskExecutor.setCorePoolSize(10);
taskExecutor.setMaxPoolSize(80);
taskExecutor.setQueueCapacity(100);
taskExecutor.initialize();
return taskExecutor;
}

@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return null;
}
}

DemoService

import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
@Service
public class DemoService {

@Async
public void a(){
while(true){
System.out.println("执行a方法");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
@Async
public void b(){
while(true){
System.out.println("执行b方法");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

测试Test

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Test {
public static void main(String[] args) {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(Config.class);
DemoService ds = ac.getBean(DemoService.class);
ds.a();
ds.b();
}
}

运行结果:循环执行

java并发原理实战(4) -- 线程的创建方式_匿名内部类_13

7.使用lambd表达式

java并发原理实战(4) -- 线程的创建方式_线程池_14


将有顺序的流分成几块,然后并行,分别执行结果。关键词是​​parallelStream​​:

演示:

/**
* 代码简洁
* 并发支持
*/
public class Demo7 {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(19,34, 56, 34);
numbers.parallelStream().forEach(System.out::println);
}
}

运行结果:

java并发原理实战(4) -- 线程的创建方式_ide_15


举报

相关推荐

0 条评论