Java编程那些事儿94——多线程实现方法1
副标题#e#
12.2 多线程实现方法
线程的观念固然较量巨大,可是在Java语言中实现线程却较量简朴,只需要凭据Java语言中对付线程的划定举办编程即可。
在实现线程编程时,首先需要让一个类具备多线程的本领,担任Thread类或实现Runnable接口的类具备多线程的本领,然后建设线程工具,挪用对应的启动线程要领开始执行即可实现多线程编程。
在一个措施中可以实现多个线程,多线程编程指在同一个措施中启动了两个或两个以上的编程形式。当启动的线程数量较量多时,对付系统资源的要求较量多,所以措施支持的最大线程数量和计较机的硬件设置相关。
在实际实现线程时,Java语言提供了三种实现方法:
1、担任Thread类
2、实现Runnable接口
3、利用Timer和TimerTask组合
下面依次先容每种实现方法的代码编写,以及各类实现之间的区别较量。
12.2.1 担任Thread类
假如一个类担任了Thread类,则该类就具备了多线程的本领,则该类则可以以多线程的方法举办执行。
可是由于Java语言中类的担任是单重担任,所以该方法受到较量大的限制。
下面以一个简朴的示例先容该种多线程实现方法的利用以及启动线程的方法。示例代码如下所示:
/**
* 以担任Thread的方法实现线程
*/
public class FirstThread extends Thread{
public static void main(String[] args) {
//初始化线程
FirstThread ft = new FirstThread();
//启动线程
ft.start();
try{
for(int i = 0;i < 10;i++){
//延时1秒
Thread.sleep(1000);
System.out.println("main:" + i);
}
}catch(Exception e){}
}
public void run(){
try{
for(int i = 0;i < 10;i++){
//延时1秒
Thread.sleep(1000);
System.out.println("run:" + i);
}
}catch(Exception e){}
}
}
#p#副标题#e#
在该措施中,通过使FirstThread担任Thread类,则FirstThread类具备了多线程的本领,凭据Java语言线程编程的划定,线程的代码必需书写在run要领内部可能在run要领内部举办挪用,在示例的代码中的run要领实现的代码浸染是每隔1秒输出一行文字。换句话说,run要领内部的代码就是自界说线程代码,可能说,自界说线程的代码必需书写在run要领的内部。
在执行FirstThread类时,和前面的执行流程一样。当执行FirstThread类时,Java虚拟机将开启一个系统线程来执行该类的main要领,main要领的内部代码凭据顺序布局举办执行,首先执行线程工具的初始化,然后执行挪用start要领。该行代码的浸染是启动线程,在执行start要领时,不阻塞措施的执行,start要领的挪用立即返回,Java虚拟机以本身的方法启动多线程,开始执行该线程工具的run要领。同时系统线程的执行流程继承凭据顺序执行main要领后续的代码,执行main要领内部的输出。
这样,在FirstThread执行时,就有了两个同时执行的流程:main流程和自界说run要领流程,换句专业点的话来说,就是该措施在执行时有两个线程:系统线程和自界说线程。这个同时执行可以从该措施的执行功效中得到越发直接的证明。
该措施的执行功效为:
run:0
main:0
main:1
run:1
main:2
run:2
main:3
run:3
main:4
run:4
main:5
run:5
main:6
run:6
main:7
run:7
main:8
run:8
main:9
run:9
从执行功效可以看到两个线程在同时执行,这将使我们进入多线程编程的时代,进入并发编程的规模,体会神奇的多线程编程的魔力。
由于两个线程中的延迟时间——1秒,是较量长的,所以看到的功效是线程纪律执行的,其实真正的线程执行顺序是不能直接担保的,系统在执行多线程措施时只担保线程是瓜代执行的,至于谁人线程先执行谁人线程后执行,则无法得到担保,需要书写专门的代码才可以担保执行的顺序。
其实,上面的代码可以简化,简化今后的代码为:
/**
* 以担任Thread的方法实现线程2
* 利用要领简化代码
*/
public class SecondThread extends Thread{
public static void main(String[] args) {
//初始化线程
SecondThread ft = new SecondThread();
//启动线程
ft.start();
print("main:");
}
public void run(){
print("run:");
}
private static void print(String s){
try{
for(int i = 0;i < 10;i++){
//延时1秒
Thread.sleep(1000);
System.out.println(s + i);
}
}catch(Exception e){}
}
}
#p#分页标题#e#
在该示例代码中,将反复的代码组织称print要领,别离在main要领和run要领内部挪用该要领。需要出格强调的是,在run要领内部挪用的要领,也会以多线程多线程的方法被系统执行,这样越发利便代码的组织。
其实在实际实现时,还可以把线程以单独类的形式呈现,这样实现的代码如下所示:
/**
* 测试类
*/
public class Test {
public static void main(String[] args) {
//初始化线程
ThirdThread ft = new ThirdThread();
//启动线程
ft.start();
try{
for(int i = 0;i < 10;i++){
//延时1秒
Thread.sleep(1000);
System.out.println("main:" + i);
}
}catch(Exception e){}
}
}
/**
* 以担任Thread类的方法实现多线程3
* 以单独类的实现组织代码
*/
public class ThirdThread extends Thread {
public void run(){
try{
for(int i = 0;i < 10;i++){
//延时1秒
Thread.sleep(1000);
System.out.println("run:" + i);
}
}catch(Exception e){}
}
}
在该示例代码中,ThirdThread类是一个单独的线程类,在该类的run要领内部实现线程的逻辑,利用该种布局切合面向工具组织代码的方法。需要启动该线程时,和前面启动的方法一致。
一个类具备了多线程的本领今后,可以在措施中需要的位置举办启动,而不只仅是在main要领内部启动。
对付同一个线程类,也可以启动多个沟通的线程,譬喻以ThirdThread类为例,启动两次的代码为:
ThirdThread t1 = new ThirdThread();
t1.start();
ThirdThread t2 = new ThirdThread();
t2.start();
而下面的代码是错误的
ThirdThread t1 = new ThirdThread();
t1.start();
t1.start(); //同一个线程不能启动两次
当自界说线程中的run要领执行完成今后,则自界说线程将自然灭亡。而对付系统线程来说,只有当main要领执行竣事,并且启动的其它线程都竣事今后,才会竣事。当系统线程执行竣事今后,则措施的执行才真正竣事。
总之,担任Thread类可以使该类具备多线程的本领,需要启动该线程时,只需要建设该类的工具,然后挪用该工具中的start要领,则系统将自动以多线程的发谁人是执行该工具中的run要领了。
固然该种方法受到Java语法中类的单重担任的限制,可是在实际的项目中照旧得到了较量遍及的利用,是一种最根基的实现线程的方法。