多线程基础知识
本文主要讲了多线程的基本概念、使用方法,线程同步,线程状态等内容。
一、简单概念
1、进程和线程的区别
进程:每个进程都有独立的代码和数据空间
线程:同一类线程共享代码和数据空间
多进程是指操作系统能同时运行多个任务,并行执行方式,多线程是指在同一个程序中有多个顺序流执行,涉及并发执行。
二、实现多线程的方式
1、继承Thread类
继承Thread类需要重写run()方法,其中run()方法的方法体就是需要完成的任务。当创建这个线程类对象时就会创建这个新的线程,通过调用线程的start()方法,使线程进入就绪状态。
下面(见代码)package com.xiao.test.thread.basethread;
/**
* 继承Thread类形式
* @author yangchangshou
*
*/
public class extendThread extends Thread {
private String tname;
public extendThread(String tname){
this.tname=tname;
}
private int i=0;
public void run(){
for (i=0;i<5;i++){
System.out.println(Thread.currentThread().getName()+"-----"+i);
}
}
}
public static void main(String args[]){
extendThread t1=new extendThread("A");
extendThread t2=new extendThread("B");
t1.start();
t2.start();
}
运行结果如图:
程序启动main()方法的时候,主线程main在main()调用时候被创建,然后调用两个对象的start()方法,启动另外两个线程。由结果可以看出,线程执行的顺序不固定,由占用CPU资源顺序决定。
基础Thread()方法时,如果同一个对象调用两次start()方法,则会抛出异常:
public static void main(String args[]){
extendThread t1=new extendThread("A");
extendThread t2=t1;
t1.start();
t2.start();
}
2、实现Runnable接口
实现Runnable接口也需要重写run()方法,再启动多线程的时候需要先通过Thread类的构造方法Thread(Runnable target) 构造出对象,然后调用Thread对象的start()方法来运行多线程代码。
下面(见代码)
package com.xiao.test.thread.basethread;
/**
* 实现Runnable接口
* @author yangchangshou
*
*/
public class implRunnable implements Runnable{
private String name;
public implRunnable(String name) {
this.name=name;
}
private int i=0;
@Override
public void run() {
for(i=0;i<5;i++){
System.out.println(name+"运行"+"---"+i);
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String args[]){
new Thread(new implRunnable("C")).start();
new Thread(new implRunnable("D")).start();
}
运行结果如下:继承类和实现接口两种方式的区别:
继承Thread类因为同一个对象两次调用start()方法会抛出异常,所以不能实现资源的共享,对多线程并发操作,竞争同一个对象来说,就受到了局限,而实现Runnable接口则不会发生这种情况。总之,实现Runnable接口的形式更适合多个相同的程序代码的线程去处理同一个资源,避免java中的单继承的限制。
三、线程间的状态转换
1、新建状态(New):新创建了一个线程对象。
2、就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法。该状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用权。
3、运行状态(Running):就绪状态的线程获取了CPU,执行程序代码。
4、阻塞状态(Blocked):阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的情况分三种:
(一)、等待阻塞:运行的线程执行wait()方法,JVM会把该线程放入等待池中。
(二)、同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池中。
(三)、其他阻塞:运行的线程执行sleep()或join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。
5、死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。
上一篇: 多线程基础知识