一.进程与线程
- 进程:每一个独立运行的程序称为一个进程
- 线程:线程时一个进程内部的一条执行路径,Java虚拟机允许程序并发的运行多个执行路径
*进程中执行运算的最小单位——>线程<——处理机分配
- 进程与线程的区别:
(1)进程有独立的运行地址空间,一个进程崩溃后不会影响到其他的进程,而线程只是 一个进程中的一个执行路径,如果有一条线程奔溃了,可能会影响到进程中的的其他线程
(2)线程有自己的栈和局部变量,多个线程共享同一进程的地址空间
(3)一个进程至少有一个线程
- 多线程
(1)多线程 就是在一个进程中创建多个线程,每个线程完成一个任务
(2)优点:
<1>多线程技术使程序的响应速度更快
<2>提高资源利用率
<3>程序设计更加简单
- 多线程的执行特性
(1)随机性(一部执行):谁“抢”到CPU,谁执行
(2)宏观上同时执行,微观上同一时刻只能执行一个线程(多核除外)
二.线程的创建和启动
1.两种创建 新线程的方式
<1>第一种方式:将类声明为Thread的子类并重写run()方法
格式:
class MygThread extends Thread{
Public void run(){
线程具体执行代码
}
}
创建此线程类的实例并启动:
MyThread thread1=new MyThread()
Thread1.start(); //启动线程
2.线程的基本使用方法
(1)public void start():是该线程开始执行
(2)public static Thread currentThread(): 返回对当前正在执行的线程对象的引用
(3)public final void seetName(String str):改变线程名称
(4)public final void setDDeamon(boolean on):将该线程标记为守护线程或用户线程
(5)public static void sleep(long millis):线程休眠指定毫秒数
(6)public final void join():当前线程必须等待,直到调用join()方法的线程对象所对应的线程运行完毕,当前线程才恢复执行
(7)public static void yield():线程礼让,但操作系统可以忽略这个礼让请求
例1(以创建线程为例):
创建线程:
package thread;
public class ThreadDemo extends Thread {
public ThreadDemo() {
}
public ThreadDemo(String name) {
super(name);
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName()+"循环输出i="+i);
}
super.run();
}
}
实例化线程测试:
package thread;
public class ThreadTest {
public static void main(String[] args) {
ThreadDemo thread=new ThreadDemo("线程A——>");
thread.start();
ThreadDemo thread1=new ThreadDemo("线程B——>");
thread1.start();
}
}
运行结果:
线程A——>循环输出i=0
线程B——>循环输出i=0
线程A——>循环输出i=1
线程A——>循环输出i=2
线程A——>循环输出i=3
线程B——>循环输出i=1
线程A——>循环输出i=4
线程B——>循环输出i=2
线程B——>循环输出i=3
线程A——>循环输出i=5
线程B——>循环输出i=4
线程A——>循环输出i=6
线程B——>循环输出i=5
线程A——>循环输出i=7
线程B——>循环输出i=6
线程A——>循环输出i=8
线程B——>循环输出i=7
线程B——>循环输出i=8
线程A——>循环输出i=9
线程B——>循环输出i=9
例2(以线程中的休眠方法为例):
创建线程:
package thread;
public class ThreadDemo extends Thread {
public ThreadDemo() {
}
public ThreadDemo(String name) {
super(name);
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName()+"循环输出i="+i);
}
super.run();
}
}
测试休眠方法:
package thread;
public class ThreadTest {
public static void main(String[] args) {
ThreadDemo thread=new ThreadDemo("线程A——>");
thread.start();
ThreadDemo thread1=new ThreadDemo("线程B——>");
thread1.start();
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(1000);//当前线程休眠1000ms
} catch (InterruptedException e) {
System.out.println("捕获到的已常为:"+e.getMessage());
}
System.out.println(Thread.currentThread().getName()+"线程——>i="+i);
}
}
}
运行结果:
线程A——>循环输出i=0
线程A——>循环输出i=1
线程A——>循环输出i=2
线程A——>循环输出i=3
线程A——>循环输出i=4
线程A——>循环输出i=5
线程A——>循环输出i=6
线程A——>循环输出i=7
线程A——>循环输出i=8
线程A——>循环输出i=9
main线程——>i=0
main线程——>i=1
main线程——>i=2
main线程——>i=3
main线程——>i=4
main线程——>i=5
main线程——>i=6
main线程——>i=7
main线程——>i=8
main线程——>i=9
当前线程运行所用时间:10s
例3(以线程中的join方法为例):
创建线程类:
package thread;
public class ThreadDemo extends Thread {
public ThreadDemo() {
}
public ThreadDemo(String name) {
super(name);
}
@Override
public void run() {
for (int i = 0; i < 20; i++) {
System.out.println(Thread.currentThread().getName()+"循环输出i="+i);
}
super.run();
}
}
测试join()方法类:
package thread;
public class ThreadModth {
public static void main(String[] args){
ThreadDemo thread=new ThreadDemo("线程一——>");
thread.start();
for (int i = 1; i < 20; i++) {
if(i==10){
try {
thread.join();//当前线程休眠, 直到调用join方法的线程 执行完毕,当前线程开始执行
} catch (InterruptedException e) {
System.out.println("捕获到的异常为:"+e.getMessage());
}
}
System.out.println(Thread.currentThread().getName()+"线程——>i="+i);
}
}
}
运行结果:
main线程——>i=1
main线程——>i=2
线程一——>循环输出i=0
main线程——>i=3
线程一——>循环输出i=1
main线程——>i=4
线程一——>循环输出i=2
main线程——>i=5
线程一——>循环输出i=3
main线程——>i=6
线程一——>循环输出i=4
main线程——>i=7
线程一——>循环输出i=5
main线程——>i=8
线程一——>循环输出i=6
main线程——>i=9
线程一——>循环输出i=7
线程一——>循环输出i=8
线程一——>循环输出i=9
线程一——>循环输出i=10
线程一——>循环输出i=11
线程一——>循环输出i=12
线程一——>循环输出i=13
线程一——>循环输出i=14
线程一——>循环输出i=15
线程一——>循环输出i=16
线程一——>循环输出i=17
线程一——>循环输出i=18
线程一——>循环输出i=19
main线程——>i=10
main线程——>i=11
main线程——>i=12
main线程——>i=13
main线程——>i=14
main线程——>i=15
main线程——>i=16
main线程——>i=17
main线程——>i=18
main线程——>i=19
二.线程的生命周期(状态转换)
1.线程的状态
2.要想实现多线程,必须在主线程中创建新的线程对象,任何线程都具有五种状态:创建,就绪,运行,阻塞,终止
状态图:
3.线程的停止
(1)如果线程的run()方法中执行的是一个重复执行的循环,可以提供一个标记来控制循环是否执行吧
(2)如果线程因为执行sleep()方法或是wait()方法而进入了阻塞状态,此时想要停止它,可以使用interrupt(),程序会抛出InterruptException异常
(3)如果程序因为输入输出的等待而阻塞,基本上 必须等待输入输出动作完成后才能离开阻塞状态,无法用interrupt() 方法来使线程离开run()方法,要想离开,只能通过引发一个异常
例1.(停止循环线程)
创建循环线程:
package stopthread;
public class LoopThread extends Thread{
private boolean flag=true;//设置线程停止标志
public void setFlag(boolean flag) {
this.flag = flag;
}
@Override
public void run() {
while(flag){
System.out.println("当前 线程正在运行....");
}
}
}
测试停止循环线程:
package stopthread;
public class StopLoop {
public static void main(String[] args) {
long startTime= System.currentTimeMillis();//开始线程时间
LoopThread lt=new LoopThread();
lt.start();
try {
Thread.sleep(3000);//当前线程休眠3000ms
} catch (InterruptedException e) {
System.out.println("捕获到的异常为:"+e.getMessage());
}
lt.setFlag(false);
System.out.println("end............");
long destTime=System.currentTimeMillis();//结束线程时间
System.out.println("执行完线程共用时间:"+(destTime-startTime)/1000+"s");
}
}
运行结果:
当前 线程正在运行....
当前 线程正在运行....
当前 线程正在运行....
当前 线程正在运行....
当前 线程正在运行....
当前 线程正在运行....
当前 线程正在运行....
当前 线程正在运行....
当前 线程正在运行....
当前 线程正在运行....
当前 线程正在运行....
...................
...................
end............
执行完线程共用时间:3s
例2.(以中断休眠为例 )
创建休眠中断线程:
package stopthread;
public class InterruptThread extends Thread{
private String name;
public InterruptThread(String name) {
super(name);
this.name = name;
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"开始执行");
System.out.println("准备休息5s");
long startTime=System.currentTimeMillis();// 线程开始时间
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
System.out.println("为什么要叫醒我?");
}
long destTime=System.currentTimeMillis();//线程完毕时间
System.out.println(Thread.currentThread().getName()+"执行完毕");
System.out.println("执行线程所用时间:"+(destTime-startTime)/1000+"s");
}
}
测试终端休眠:
package stopthread;
public class StopInterrupt {
public static void main(String[] args) {
InterruptThread it=new InterruptThread("线程一——>");
it.start();
try {
Thread.sleep(2000);//当前线程休眠2000ms
} catch (InterruptedException e) {
e.printStackTrace();
}
it.interrupt();//打断这个线程,使之抛出InterruptedException异常
}
}
运行结果:
线程一——>开始执行
准备休息5s
为什么要叫醒我?
线程一——>执行完毕
执行线程所用时间:2s
原文地址:http://blog.51cto.com/13501268/2071897