1 概述
进程:进程是操作系统结构的基础,是一个正在执行的程序,是可以分配给处理器并由其执行的一个实体。
线程:线程是进程中独立运行的子任务,是操作系统能够进行运算调度的最小单位。
多线程:程序在同一时间内运行多种任务,由于CPU在这些任务之间的切换十分的快,使得用户觉得这些任务就是在同时运行,使用多线程可以大大提升系统的运行效率。
2 Java创建线程的两种方式
众所周知,Java可以通过两种不同的方式创建线程,即继承Thread类并复写run方法,或者实现Runnable接口。两种方法的不同点如下:
- 由于Java只支持单继承,如果通过继承Thread类的方式,就不能继承其他的类了,而通过实现Runnable接口的方式就可以避免单继承的局限。
-
实现Runnable接口的方式创建的线程可以处理同一资源,从而实现资源的共享。为了说明这一点,请参考如下l两段代码:
/**
* Created by fubinhe on 16/8/28.
*/
class TicketSellThread extends Thread {
private int ticketNum = 100;
@Override
public synchronized void run() {
while (ticketNum > 0) {
System.out.println(Thread.currentThread().getName() +
" is selling ticket No. " + ticketNum--);
}
}
}
public class ThreadDemo {
public static void main(String[] args) {
TicketSellThread t1 = new TicketSellThread();
TicketSellThread t2 = new TicketSellThread();
t1.start();
t2.start();
}
}
/**
* Created by fubinhe on 16/8/28.
*/
class TicketSellRunnable implements Runnable {
private int ticketNum = 100;
@Override
public synchronized void run() {
while (ticketNum > 0) {
System.out.println(Thread.currentThread().getName() +
" is selling ticket No. " + ticketNum--);
}
}
}
public class ThreadDemo {
public static void main(String[] args) {
TicketSellRunnable ticketSellRunnable = new TicketSellRunnable();
Thread t1 = new Thread(ticketSellRunnable);
Thread t2 = new Thread(ticketSellRunnable);
t1.start();
t2.start();
}
}
<span style="font-family: Arial, sans-serif; background-color: rgb(255, 255, 255);">在以上两段代码中,前者的两个线程各自独立,彼此都用于自己的资源,即100张票,而后者可以共享这100张票的资源。当然,第一段代码可以通过给ticketNum变量加上static属性也能达到共享资源的目的,但是这样ticketNum的生命周期过长。</span>
综合以上两点,一般情况下通过实现Runnable接口的方式创建线程。
3 两种方式的结合
如果将以上两种创建线程的方式相结合,效果是怎样呢?请参考以下代码:
/**
* Created by fubinhe on 16/8/28.
*/
public class ThreadDemo {
public static void main(String[] args) {
new Thread(new Runnable() {
public void run() {
System.out.println("runnable run......");
}
}){
public void run() {
System.out.println("thread run......");
}
}.start();
}
}
上述代码看起来很乱,可以稍微分析一下可以发现:主函数创建了一个匿名类,这个类是Thread的子类,其复写了run方法,当调用start方法时运行run方法里的代码,所以执行的结果是"thread run......"。而new Runnable()主要是给父类Thread的构造函数传参。查看Thread类的run方法源代码如下:
private Runnable target;
@Override
public void run() {
if (target != null) {
target.run();
}
}
而new Runnable()给父类Thread的构造函数传参就是给target变量赋值,如果在第二个run方法里调用super.run(),可以执行第一个run方法里的代码。