1,进程(process)
定义:处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位。
2,进程的特征:
A:独立性,独立的实体,拥有独立的资源,拥有自己私有地址;
B:动态性,它是正在系统中活动的指令集合,拥有自己的生命周期和不同状态;
C:并发性,多个进程可以在单个处理器上并发执行,多个进程之间不会相互影响。
3,线程(Thread)
1)定义:轻量级进程(Lightweight Process)是进程的执行单元。进程内的多条顺序执行流。
2)线程也是独立的,并发的。
4,进程和线程的关系
A, 线程是进程的组成部分,一个进程可以拥有多线程,线程必有父进程;
B, 线程拥有自己的堆栈等,但不拥有系统资源。与父进程中其他线程共享拥有的全部资源。
C, 线程的执行是抢占式的,一个线程可以是创建和撤销另一个线程,同一个进程中的多个线程之间可以并发执行。
D, 一个程序运行后至少有一个进程,一个进程可以包含多个进程,但至少有一个进程。
5,多线程优势
A, 进程之间不能共享内存,但线程之间共享内存非常容易;
B, 系统创建进程时,需要为该进程重新分配系统资源,但创建线程则代价小很多;
C, Java内置多线程功能支持。
6,线程的创建和启动
A 使用继承Thread类的方法来创建线程类
1) 使用Thread类代表线程,所有线程对象都必须是Thread类或者其子类的实例。
2) 创建和启动该种多线程的步骤如下代码所示:
- /*
- * 该程序两个目的:
- * 目的一:了解线程创建的步骤
- * 目的二:通过此例子,了解线程的执行顺序
- */
- package com.wayne.MyThread;
- //【创建线程步骤】1st,继承Thread
- public class MyFirstThread extends Thread
- {
- private int i;//创建一个标志位,用于表示程序的运行
-
- //【创建线程步骤】2nd,重写run()方法,形成线程执行体
- public void run()
- {
- for(;i<100;i++)//此处的i是成员变量i,其在new的过程中已经有初值0
- {
- //当线程类继承Thread类时,直接使用this即可获取当前线程
- System.out.println(this.getName()+" "+i);
- }
- }
-
- //main()方法代表了主线程的线程执行体
- public static void main(String[] args)
- {
- //【创建线程步骤】3rd,创建Thread的子类MyFirstThread的实例,用于创建线程对象
- MyFirstThread myFirstThread1st = new MyFirstThread();
- MyFirstThread myFirstThread2nd = new MyFirstThread();
-
- for(int i = 0;i<100;i++)
- {
- //Thread.currentThread()获取当前正在执行的线程对象
- //getName()返回调用该方法的线程名字
- System.out.println(Thread.currentThread().getName()+" "+i);
-
- if(i == 20)//当标志位运行到20时,创建两个线程
- {
- //【创建线程步骤】4th,调用start()方法启动该线程
- myFirstThread1st.start();
- myFirstThread2nd.start();
-
- //notice:直接调用线程对象的run方法,系统会认为该对象为普通对象,顺序执行下去
- //myFirstThread1st.run();
- //myFirstThread2nd.run();
- }
- }
- }
- }
复制代码
3) main()方法的方法体代表主线程的线程执行体。
4) 使用继承Thread类的方法来创建线程类时,多个线程之间无法共享线程类的实例变量。
5) 线程的两个方法
a) Thread.currentThread():返回当前正在执行的线程对象;
b) getName():返回调用该方法的线程名字。
B 通过实现Runnable接口创建线程类
1) 创建和启动该种多线程的步骤如下代码所示:
- /*
- * 该程序一个目的:
- * 目的一:了解通过实现Runnable接口来进行线程创建的步骤
- */
- package com.wayne.MyThread;
- //【创建线程步骤】1st,定义Runnable接口的实现类
- public class MyRunnableThread implements Runnable{
- private int i;//创建一个标志位,用于表示程序的运行
- //【创建线程步骤】2nd,重写Runnable接口的run方法,形成线程执行体
- @Override
- public void run() {
- for(;i<100;i++)
- {
- //当线程类实现Runnable接口时,
- //获取当前线程,只能通过Thread.currentThread()获得
- System.out.println(Thread.currentThread().getName()+" "+i);
- }
-
- }
-
- public static void main(String[] args) {
-
- for(int i = 0;i<100;i++)
- {
- //Thread.currentThread()获取当前正在执行的线程对象
- //getName()返回调用该方法的线程名字
- System.out.println(Thread.currentThread().getName()+" "+i);
-
- if(i == 50)
- {
- //【创建线程步骤】3rd,创建Runnable实现类myRunnableThread的实例
- MyRunnableThread myRunnableThread1st = new MyRunnableThread();
- MyRunnableThread myRunnableThread2nd = new MyRunnableThread();
-
- //【创建线程步骤】4th,利用Runnable实现类myRunnableThread的实例,作为Thread的target,来创建Thread对象
- //此Thread类对象才是这个线程的线程对象。
- Thread threadRunnable1st = new Thread(myRunnableThread1st,"New 1st RunnableThread");
- Thread threadRunnable2nd = new Thread(myRunnableThread2nd,"New 2nd RunnableThread");
-
- //【创建线程步骤】5th,调用线程对象的start()方法启动该线程
- threadRunnable1st.start();
- threadRunnable2nd.start();
- }
- }
- }
- }
复制代码
2) 采用Runnable对象只是线程的target,而多个线程共享一个target,因此,多个线程可以共享同一个线程类的实例变量。
C 通过使用Callable和Future创建线程
1) 创建和启动该种多线程和步骤如下代码所示:
- /*
- * 此程序的目的是了解通过实现Callable接口来进行线程创建的步骤
- */
- package com.wayne.MyThread;
- //如果通过实现Callable<Integer>来创建对象,
- //则需要导入如下的包java.util.concurrent.Callable
- import java.util.concurrent.Callable;
- import java.util.concurrent.FutureTask;
- //【创建线程步骤】1st,定义Runnable接口的实现类
- public class MyChallableThread implements Callable<Integer>
- {
- //【创建线程步骤】2nd,重写Callable<Integer>接口的call方法,形成线程执行体
- @Override
- public Integer call() throws Exception
- {
- int i = 0;
-
- for(;i<100;i++)
- {
- System.out.println(Thread.currentThread().getName()+" "+ i);
- }
- return i;
- }
-
- public static void main(String[] args)
- {
- //【创建线程步骤】3rd,创建Callable<Integer>实现类的实例
- MyChallableThread myChallableThread = new MyChallableThread();
-
- //【创建线程步骤】4th,利用FutureTask类来包装Callable<Integer>类对象
- FutureTask<Integer> target = new FutureTask<Integer>(myChallableThread);
-
- for(int i = 0;i<100;i++)
- {
- System.out.println(Thread.currentThread().getName()+" "+i);
-
- if(i == 20)
- {
- //【创建线程步骤】5th,使用FutureTask对象作为Thread对象的target
- new Thread(target,"有返回值的线程").start();
- }
-
- /*
- try
- {
- System.out.println(Thread.currentThread().getName()+"的返回值是"+target.get());
- }
- catch(Exception ex)
- {
- ex.printStackTrace();
- }
- */
- }
- }
- }
复制代码
2) call()方法:作为线程的执行体,可以返回值,也可以抛出异常。
7,创建线程的三种方式对比
A. 采用Runnable、Callable创建多线程的优缺点
优点:
1) 线程类只实现了Runnable或者Callable接口,还可以继承其他类;
2) 多个线程共享同一个target对象。
缺点:
编程稍复杂,如果需要访问当前线程,则必须使用Thread.currentThread()方法
B. 采用继承Thread类方式创建多线程的优缺点
优点:
编写简单,直接使用this即可获得当前线程;
缺点:
因为编程类已经继承Thread类,所以不能在继承其他类。
|
|