欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程资源 > 编程问答 >内容正文

编程问答

oracle的多线程怎么实现,创建线程的两个方法(Oracle官网说两种,所以我们就别说什么三种四种了)...

发布时间:2023/12/15 编程问答 39 豆豆
生活随笔 收集整理的这篇文章主要介绍了 oracle的多线程怎么实现,创建线程的两个方法(Oracle官网说两种,所以我们就别说什么三种四种了)... 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

一.有多少种实现多线程的方法?

1.不同的角度有不同的答案

2.典型的答案有两种,分别是实现Runnable接口和继承Thread类

3.但是看原理,其实Thread类实现了Runnable接口,并且看Thread类的run方法,会发现其两者本质是一样的,run方法发代码如下:

@Override

Public void run(){

if(target != null){

target.run();

}

}

方法1和方法2,也就是说“实现Runnable类”和“继承Thread类然后重写run()”在实现多线程本质上,并没有区别,都最终调用了start()方法来新建线程,这两种方法主要区别在于run()方法来源:

方法1:最终调用target.run();

方法2:run()整个都被重写

4.还有其他的实现线程的方法,例如线程池定时器等,他们也能新建线程,但是看源码,从没有逃出本质,也就是实现Runnable接口和继承Thread类。

5.所以总结来说,我们只能通过新建Thread类这一种方式来创建线程,但是类里面的run方法有两种方式来实现,第一种是重写run方法,第二种实现Runnable接口的run方法,然后再把该runnable实例传递给Thread类。除此之外,从表象上看线程池,定时器等工具类也可以创建线程,但是它们的本质都逃不过上面的范围。

二.为什么实现Runnable接口比继承Thread更好?

1.相比较,实现Runnable接口更好,一般都会优先考虑这种发放,除非迫不得已,我们是不考虑继承Thread类的。原因有三点,第一点:从代码架构考虑,具体执行的任务,即run方法,它因该和线程创建运行也就是Thread类是接偶的,不应该将两者混为一谈,所以从接偶角度来看,实现Runnable更好。第二点:如果继承Thread类,每次新建一个任务,只能为此新建一个独立的线程,而新建一个独立的线程的损耗是非常大的,它需要创建然后执行,执行完后需要销毁,而使用Runnable就可以使用线程池之类的工具,就可以大大减小创建销毁线程带来的损耗。第三点:继承了Thread类后,由于java不支持双继承,不能再继承其他的类,限制了代码的课扩展性。

线程池创建线程:

public class ThreadPool{

public static void main(String[] args){

ExecutorService executorService = Executors.newCachedThreadPool();

for(int i=0; I<100;i++){

executorService.submit(new Task(){

});

}

}

}

Class Task implements Runnable{

@Override

public void run(){

try{

Thread.sleep(500);

}catch(InterruptedException e){

e.printStackTrace();

}

System.out.println(Thread.currentThread().getName());

}

}

定时器创建线程:

public class DemoTimerTask{

public static void main(String[] args){

Timer timer = new timer();

timer.scheduleAtFixedRate(new TimerTask(){

@Override

public void run(){System.out.println(Thread.currentThread().getName());

}

},1000,1000);

}

}

匿名内部类实现线程:

public static void main(String[] args){

new Thread(){

@Override

public void run (){

System.out.println(Thread.currentThread().getName());

}

}.start();

new Thread(new Runnable(){

@Override

public void run (){

System.out.println(Thread.currentThread().getName());

}

}).start();

}

Lambda表达式实现线程:

public static void main(String[] args){

new Thread(() -> System.out.println(Thread.currentThread().getName())).start();

}

如果一个线程两次调用start方法会怎样?为什么?

会抛出一个异常(IllegalThreadStateException),因为在start方法第一行,就会误检查线程的状态,如果不是0,即不是初始状态,就会抛出异常,因为线程状态是不可逆的,所以已经执行过start后,状态改变了,就不能在执行start方法了。

start()既然也是调用的run()方法,为什么不直接调用run()而是调用start()?

因为调用start()才是真正的去启动一个新线程,会经历线程的各个生命周期,而如果直接调用run()方法,它就是个普通的run()方法,不会用子线程去调用,而直接用主线程执行的。

public static void main(String[] arg){

Runnable runnable = () -> {

System.out.println(Thread.currentThread().start());

};

runnable.run();

new Thread(runnable).start();

}

输出结果:

main

Thread-0

start()执行过程:

1.检查线程状态。

2.加入线程组。

3.调用start0()发放启动线程。

start()是被synchronized修饰的,可以保证线程安全。

由JVM创建的main线程和system组线程,并不会通过start()来启动。

注意:以上就是创建线程的方法,其中代码不保证可执行性,因为纯手打,有单子字母写错的可能。

创作挑战赛新人创作奖励来咯,坚持创作打卡瓜分现金大奖

总结

以上是生活随笔为你收集整理的oracle的多线程怎么实现,创建线程的两个方法(Oracle官网说两种,所以我们就别说什么三种四种了)...的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。