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();
    }
}

运行结果:
在这里插入图片描述

2.实现runnable接口:

执行流程:

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

在这里插入图片描述

英文翻译:

  • 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();

    }
}

运行结果:
在这里插入图片描述

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也不会被执行。

子类thread重写了run方法,根据jvm方法重写的原理,方法调用动态分派会调用子类的run方法
在这里插入图片描述

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);
    }
}

运行结果:

在这里插入图片描述

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

5.定时器

timer

看下他的api:
在这里插入图片描述
在这里插入图片描述
代码演示:

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);
    }
}

运行结果:
在这里插入图片描述

缺点:

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

5.线程池

在这里插入图片描述

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() {@Overridepublic void run() {
​                    System.out.println(Thread.currentThread().getName());}});}//停掉线程池
​        threadPool.shutdown();}
}

运行结果:
在这里插入图片描述
演示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();
    }
}

在这里插入图片描述

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();
    }
}

运行结果:循环执行
在这里插入图片描述

7.使用lambd表达式

在这里插入图片描述
将有顺序的流分成几块,然后并行,分别执行结果。关键词是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);
    }
}

运行结果:

在这里插入图片描述


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

怒放de生命2010

您的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值