Java语言中多线程的实现有3种方法
1.继承Thread类,重写run()
public class Test1 extends Thread{
@Override
public void run(){
System.out.println("thread begin!");
}
public static void main(String[] args){
Test1 test = new Test1();
test.start();
}
}
该线程实例的创建依赖于Thread类,那么看下源码Thread类的实现:
public class Thread implements Runnable{
// ......
//先将新建的线程添加进线程组中,标志为可运行状态
public synchronized void start() {
if (threadStatus != 0)
throw new IllegalThreadStateException();
group.add(this); //将当前新建的线程对象添加到线程组
boolean started = false;
try {
start0();
started = true; //标识为可运行状态
} finally {
try {
if (!started) {
group.threadStartFailed(this);
}
} catch (Throwable ignore) {
}
}
}
@Override
public void run() {
if (target != null) {
target.run();
}
}
}
需要注意的是:调用start()后并不是立即执行多线程,而且Thread本质是实现Runnable接口的一个实例而已
我们通过调用Thread类的start()方法来启动一个线程,
这时此线程是处于就绪状态,
并没有运行。
然后通过此Thread类调用方法run()来完成其运行操作的,
这里方法run()称为线程体,
它包含了要执行的这个线程的内容,
Run方法运行结束,
此线程终止,
而CPU再运行其它线程。
2.实现Runnable接口,实现接口中的run()
主要步骤:
自定义类并实现Runnable接口,实现run()
创建Thread对象,用实现Runnable接口的对象作为参数实例化该Thread对象
调用Thread的start()
public class Test2 implements Runnable{
@Override
public void run(){
System.out.println("thread begin!");
}
public static void main(String[] args){
Test2 test = new Test2();
test.run();
}
}
Runnable接口的源码:
public interface Runnable {
public abstract void run();
}
通过两个demo我们发现,其实不管是继承Thread类还是实现Runnable接口来实现多线程,最终都是通过Thread对象的API控制线程
不过,我们也发现run()方法和start()方法似乎有着相似的功能,但又不一样。
试着比较下他们的区别
class ThreadDemo extends Thread{
@Override
public void run(){
System.out.println("ThreadDmo:begin!");
try {
Thread.sleep(1000);
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}finally{
System.out.println("ThreadDemo:end!");
}
}
}
public class Test3 {
public static void test1(){
System.out.println("test1:begin!");
Thread t1 = new ThreadDemo();
t1.start();
System.out.println("test1:end!");
}
public static void test2(){
System.out.println("test2:begin!");
Thread t2 = new ThreadDemo();
t2.run();
System.out.println("test2:end");
}
public static void main(String[] args){
test1();
try {
Thread.sleep(5000);
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}finally{
System.out.println();
test2();
}
}
}
输出:
test1:begin!
test1:end!
ThreadDmo:begin!
ThreadDemo:end!
test2:begin!
ThreadDmo:begin!
ThreadDemo:end!
test2:end
从test1的运行结果可以看出,线程t1是从test1方法结束后才执行的System.out.println(“test1:end”)语句不需要等待t1.start()运行结果就可以执行
test1中调用start()方法是异步的。所以main()线程与t1线程是异步的。从test2的运行结果可以看出,调用t1.run()是同步的调用方法,因为System。out.println(“test2:end”)。只有等t1.run()调用结束后才可执行