什么是线程?
线程与进程相似,但线程是一个比进程更小的执行单位。一个进程在其执行的过程中可以产生多个线程。与进程不同的是同类的多个线程共享同一块内存空间和一组系统资源,所以系统在产生一个线程,或是在各个线程之间作切换工作时,负担要比进程小得多,让使用者感觉到这些线程在同时执行 ,也正因为如此,线程也被称为轻量级进程。
什么是进程?
进程是程序的一次执行过程,是系统运行程序的基本单位,因此进程是动态的。系统运行一个程序即是一个进程从创建,运行到消亡的过程。简单来说,一个进程就是一个执行中的程序,它在计算机中一个指令接着一个指令地执行着,同时,每个进程还占有某些系统资源如CPU时间,内存空间,文件,文件,输入输出设备的使用权等等。换句话说,当程序在执行时,将会被操作系统载入内存中。
线程和进程有什么不同?
线程是进程划分成的更小的运行单位。线程和进程最大的不同在于基本上各进程是独立的,而各线程则不一定,因为同一进程中的线程极有可能会相互影响。从另一角度来说,进程属于操作系统的范畴,主要是同一段时间内,可以同时执行一个以上的程序,而线程则是在同一程序内几乎同时执行一个以上的程序段。
如何创建线程:
1.继承Thread类创建线程:
1)定义Thread类的子类,并重写该类的run()方法,该方法的方法体就是线程需要完成的任务,run()方法也称为线程执行体。
2)创建Thread子类的实例,也就是创建了线程对象
3)启动线程,即调用线程的start()方法
public class TestThread01 {
public static void main(String[] args) {
MyThread thread = new MyThread();
thread.start();
}
}
class MyThread extends Thread{
private static int num = 0;
public MyThread(){
num++;
}
@Override
public void run(){
System.out.println("主动创建创建的第"+num+"线程");
}
}
2.实现Runnable接口创建线程:(推荐实现Runnable接口方式开发多线程,因为Java单继承但是可以实现多个接口。
1)定义Runnable接口的实现类,一样要重写run()方法,这个run()方法和Thread中的run()方法一样是线程的执行体
2)创建Runnable实现类的实例,并用这实例作为Thread的target来创建Thread对象,这个Thread对象才是真正的线程对象
3)第三部依然是通过调用线程对象的start()方法来启动线程
注意,这种方式必须将Runnable作为Thread类的参数,然后通过Thread的start方法来创建一个新线程来执行该子任务。如果调用Runnable的run方法的话,是不会创建新线程的,这跟普通的方法调用没有任何区别。
public class TestThread02 {
public static void main(String[] args) {
System.out.println("主线程ID:"+Thread.currentThread().getId());
MyRunnable runnable = new MyRunnable();
Thread thread = new Thread(runnable);
thread.start();
}
}
class MyRunnable implements Runnable{
public MyRunnable() {}
@Override
public void run() {
System.out.println("子线程ID:"+Thread.currentThread().getId());
}}
3)使用Callable和Future创建线程:
1)具体是创建Callable接口的实现类,并实现clall()方法。
2)并使用FutureTask类来包装Callable实现类的对象,且以此FutureTask对象作为Thread对象的target来创建线程。
注意:Callable与Runnable十分相似,但是是有返回值的。Callable接口是一个参数化的类型,只有一个call方法。
public class TestThread03 {
public static void main(String[] args) {
Callable<Integer> myCallable = new MyCallable();//创建一个mycallable的对象
FutureTask<Integer> futureTask = new FutureTask<Integer>(myCallable);//使用FutureTask来包装MyCallable对象
for (int i = 0 ; i < 100 ; i++){
System.out.println(Thread.currentThread().getName() + " " + i);
if (i == 30){
Thread thread = new Thread(futureTask);
thread.start();
}
}
System.out.println("主线程for循环执行完毕!");
try{
int sum = futureTask.get();
//MyCallable中sum的返回值:4950会永远最后输出,原因在于通过futureTask.get()方法获取子线程call()方法的返回值时,
// 当子线程此方法还未执行完毕,futureTask.get()方法会一直阻塞,直到call()方法执行完毕才能取到返回值。
System.out.println("MyCallable中sum的返回值:" + sum);
}catch (InterruptedException e){
e.printStackTrace();
}
catch (Exception e){
e.printStackTrace();
}
}
}
class MyCallable implements Callable<Integer>{
private int sum = 0;
@Override//与Runnable重写run()方法不同色是,call()方法是有返回值的
public Integer call() throws Exception {
for (int i = 0 ; i < 100 ; i++){
System.out.println(Thread.currentThread().getName() + i);
sum += i;
}
return sum;
}
}