Java多线程一
一、线程和进程
java开发中,程序是按照顺序执行的,大多数情况下都是单线程编程,即只有一条程序顺序流---从main方法开始执行,依次向下执行,如果在某行代码遇见阻塞的话,程序就会停滞不前。但是在实际情况中,单线程的功能往往是有限的,比如向多个客户端提供服务且各个客户端不相互干扰,这时,多线程闪亮登场了,所谓多线程,包含了多条程序顺序流且他们之间不相互干扰。
在了解什么叫做线程之前,先了解一下什么叫做进程。
进程:是系统进行资源分配和调度的一个独立单位。几乎所有操作系统都支持多个任务的执行,当一个任务(一个程序)进入内存运行时,即变成一个进程。进程是处于运行过程中的程序,并具有一定的独立功能。
进程的3个特质:
1、独立性:进程是系统中独立存在的实体,它拥有自己独立的资源和私有的地址空间。在没有经过进程本身同意的情况下,一个用户进程不可以直接访问其他进程的地址空间。
2、动态性:进程是处于运行状态的程序,程序本身是一个静态的指令集合。进程拥有自己的生命周期和各种不同的状态,而程序不具备这些。
3、并发性:多个进程可以在单个处理器上并发执行,且不会相互影响。
并发(concurrency)和并行(parallel)的区别:并发指的是在同一时刻只能有一条指令被执行,但多个进程的指令被快速轮换执行,使得宏观上具有多个进程同时执行的效果;
并行指的是在同一时刻,多条指令在多个处理器上同时执行。
对于CPU而言,它在一个时间点只能执行一个进程,所谓多进程,即CPU不断的在多个进程之间轮换执行,多进程并发实现根据不同的操作系统和硬件有不同的策略,常用的有共用式的多任务操作和效率更高,使用者更多的抢占式多任务操作策略。
下来看一下线程:
线程(thread)是进程的组成部分,是进程的执行单元,一个进程可以有多个线程,一个线程必须有一个父进程,线程有自己的堆栈,程序计数器和局部变量,但是不拥有系统资源,它与其他线程共享进程所有用的全部系统资源和内存。每个线程是相互独立的,并且线程的调度和管理是由进程本身负责。
归纳一下:操作系统可以执行多个进程,进程可以执行多个线程;
线程于进程,相当于进程于操作系统。
多线程的优势:
1、进程之间不能共享内存,线程之间共享进程的内存空间,因此程序具有更高的执行效率;
2、系统创建进程的时候需要为进程分配系统资源,但是线程不需要,因此实现并发任务时线程比进程效率更高;
3、Java有内置的多线程功能支持,能够简化java的多线程编程
二、多线程的几种实现方式
共有三种实现方式:
1、继承Theread类;
2、实现Runnable接口;
3、使用Callable和Future;
1、继承Theread类;
1 public class FirstThread extends Thread { 2 3 private int i; 4 5 public void run() { 6 7 for (; i < 50; i++) { 8 9 System.out.println(this.getName()+" "+i); 10 } 11 } 12 13 public static void main(String[] args) { 14 15 for (int i = 0; i < 50; i++) { 16 17 System.out.println(Thread.currentThread().getName()+" "+i); 18 19 if (i == 20) { 20 21 new FirstThread().start(); //创建第一个线程 22 23 new FirstThread().start();//创建第二个线程 24 25 } 26 27 } 28 } 29 30 }
运行结果(只截取一部分):
main 46
main 47
main 48
main 49
Thread-1 1
Thread-0 5
Thread-0 6
Thread-0 7
Thread-1 2
Thread-0 8
Thread-1 3
Thread-0 9
Thread-1 4
Thread-0 10
2、实现Runnable接口;
1 public class SecondThread implements Runnable { 2 3 private int i; 4 5 public void run() { 6 for (; i < 50; i++) { 7 8 System.out.println(Thread.currentThread().getName() + " " + i); 9 } 10 } 11 12 public static void main(String[] args) { 13 14 for (int i = 0; i < 50; i++) { 15 16 System.out.println(Thread.currentThread().getName() + " " + i); 17 18 if (i == 20) { 19 20 SecondThread st = new SecondThread(); 21 22 new Thread(st).start(); //创建第一个线程 23 24 new Thread(st).start();//创建第二个线程 25 26 } 27 } 28 } 29 }
运行结果(只截取一部分):
main 45
Thread-0 23
main 46
Thread-1 24
main 47
Thread-0 25
main 48
Thread-1 26
main 49
Thread-0 27
Thread-1 28
Thread-0 29
Thread-1 30
Thread-0 31
Thread-1 32
Thread-0 33
3、使用Callable和Future;
1 public class ThirdThread implements Callable<Integer> { 2 3 @Override 4 public Integer call() throws Exception { 5 int i = 0; 6 for (; i < 50; i++) { 7 8 System.out.println(Thread.currentThread().getName() + " " + i); 9 } 10 return i; 11 } 12 13 public static void main(String[] args) { 14 15 ThirdThread tt = new ThirdThread(); 16 FutureTask< Integer> task = new FutureTask<Integer>(tt); 17 18 for (int i = 0; i < 50; i++) { 19 20 System.out.println(Thread.currentThread().getName() + " " + i); 21 22 if (i == 20) { 23 24 new Thread(task).start(); 25 26 } 27 } 28 try { 29 30 System.out.println("子线程的返回值是"+" "+ task.get()); 31 32 } catch (Exception e) { 33 e.printStackTrace(); 34 } 35 } 36 }
运行结果(只截取一部分):
Thread-0 44
Thread-0 45
Thread-0 46
Thread-0 47
Thread-0 48
Thread-0 49
子线程的返回值是 50