学习JAVA多线程,对多线程的实现方式及应用做一些总结,为以后留存查看。
进程与线程
进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程中可以启动多个线程。
线程是指进程中的一个执行流程,一个进程中可以运行多个线程。线程总是属于某个进程,进程中的多个线程共享进程的内存。
关于进程和线程的知识,参考阮一峰的网络日志。
对于JAVA中的线程相关知识,可以参考Java 线程简介。
JAVA线程实现
JAVA实现线程有两种方式,一是继承类:java.lang.Thread(),二是实现接口:java.lang.Runnable()。
1. 实现Runnable()接口
查看源码可知,该接口只定义了一个run()方法,实现时只需要实现run()方法即可。该方法只在指定线程启动后未停止阶段运行,如果没有将实现该接口的类作为参数来创建新的线程,则该类只在当前线程下运行。具体的说明参考Oracle的Runnable()接口说明。
public interface Runnable {
public abstract void run();
}
简单的例子:
public class MyRunnable implements Runnable {
private String name;
public MyRunnable(String name) {
this.name = name;
}
public void run() {
System.out.println("name:" + name + " 线程ID:" + Thread.currentThread().getId());
}
}
2. 继承Thread()类
查看源码发现,Thread()其实也是实现了Runnable()接口,也有将实现Runnable()接口的类作为参数的构造方法。具体细节,可以阅读源码或参考Oracle的Thread()类说明.
public class Thread implements Runnable {
......
private Runnable target;
......
public Thread(Runnable target) {
init(null, target, "Thread-" + nextThreadNum(), 0);
}
......
@Override
public void run() {
if (target != null) {
target.run();
}
}
......
}
将实现Runnable()的类作为参数,另起线程:
MyRunnable runnable_1 = new MyRunnable("runnable_1");
// 实现Runnable接口,只有run()方法,没有start(),在主线程中执行
// runnable_1.run();
// 另起一个线程,runnable作为参数
new Thread(runnable_1).start();
测试
Test_1: run()和start()的异同
线程类,继承Thread()类:
class MyThread extends Thread {
private String name;
public MyThread(String name) {
this.name = name;
}
@Override
public void run() {
System.out.println(
"name:" + name + " ,线程ID:" + Thread.currentThread().getId() + "---时间为:" + System.currentTimeMillis());
}
}
main()方法:
public class TestMythread {
public static void main(String[] args) {
System.out.println("主线程ID:" + Thread.currentThread().getId() + "---时间为:" + System.currentTimeMillis());
MyThread thread_1 = new MyThread("小明");
// 起一个新的线程执行
thread_1.start();
MyThread thread_2 = new MyThread("小芳");
// run()方法会在主线程中执行,不会再起一个新线程执行
thread_2.run();
}
}
运行结果:
主线程ID:1---时间为:1481271550678
name:小明 ,线程ID:9---时间为:1481271550679
name:小芳 ,线程ID:1---时间为:1481271550679
结果分析:
start()方法会另起一个新的线程执行程序,执行线程的ID不一样;而run()方法是在主线程中执行程序,执行线程的ID和主线程ID一样。
Test_2: Thread()与Runnable()
实现Runnable()接口的类:
public class MyRunnable implements Runnable {
private String name;
public MyThread(String name) {
this.name = name;
}
@Override
public void run() {
System.out.println(
"name:" + name + " ,线程ID:" + Thread.currentThread().getId() + "---时间为:" + System.currentTimeMillis());
}
}
main()方法:
public class TestMythread {
public static void main(String[] args) {
System.out.println("主线程ID:" + Thread.currentThread().getId() + "---时间为:" + System.currentTimeMillis());
MyRunnable thread_1 = new MyRunnable("小明");
// 实现Runnable接口,只有run()方法,没有start(),在主线程中执行
thread_1.run();
// 另起一个线程,runnable作为参数
new Thread(thread_1).start();
}
}
运行结果:
主线程ID:1---时间为:1481275074133
name:小明 线程ID:1---时间为:1481275074134
name:小明 线程ID:9---时间为:1481275074134
结果分析:
MyRunnable()类实现了Runnable()接口,重写了run()方法,在new出新的类时,调用run()方法,会在主线程中运行(线程ID相同);当该类作为参数new新的线程,调用start()方法时,就会另起一个线程运行(线程ID不同),此时如果调用新启线程的run()方法,也是在主线程中执行。