您的位置:首页 > 职场人生

黑马程序员-----java线程学习与总结

2014-09-18 23:47 531 查看
------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

1、线程的概念

Thread,是一个进程更加微观的一个对象。进程是OS任务调度的最基本单位。

独立性:线程不能独立存在,线程依赖于进程存在。

存储区域:进程中的数据存在堆栈中,线程的数据存在于寄存器中。

粒度:线程小,进程大。

2、Java中关于线程的API

线程的API包括一个java.lang.Thread类和一个接口java.lang.Runnable接口。

Runnable接口只有一个抽象run()方法。而Thread类实际上是对Runnable接口的实现。

Thread的方法大概分为3类:

获取线程信息方法:getName()/getPriority()

设置线程信息方法:

setName()/setPriority()

有关线程生命周期的方法

Sleep()/join()/interrupt()/interrupted()/isAlive()/run()/resume()/suspend()/start()

3、实现线程的方式

Thread():构造一个缺省线程类

Thread(String name):构造一个名称为name的线程类

Thread(Runnable r):构造由R实现的线程类

Thread(Runnable r,String name):构造由R实现,名称为name的线程。

我们定义线程类,核心机制重写run()方法,在run()方法中写线程的功能代码。

(1)自定义的类继承Thread类实现

第一步:定义run()方法

第二步:创建线程对象并启动线程,通过start()方法来间接调用run()方法,不能直接调用run()方法。

(2)自定义的类实现Runnable接口实现

第一步:定义run()方法

第二步:创建线程对象并启动线程。

如下:
package com.tai.GX;

public class ThreadText
{
public static void main(String[] args)
{
//第一种实现方式  创建匿名Thread的子类,复写Thread的run方法 运行的时候就会自动调用run方法
new Thread(){
public void run() {
while (true)
{
try
{
Thread.sleep(1500);
System.out.println(this.getName());//这里的this 就是当前正在运行的线程  相当于 Thread.currentThread
system.out.println("this Thread can do something footloose!");
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
};
}.start();
//第二种实现方式 创建Thread是传入一个Runnable接口的子类并复写其Run方法
new Thread(new Runnable()
{
@Override
public void run()
{
while (true)
{
try
{
Thread.sleep(1500);
System.out.println(Thread.currentThread().getName());
system.out.println("this Thread can do something footloose!");
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}).start();

//因为Thread也实现了Runnable接口这里也可以这样用,我就是试试  其实不合理的
new Thread(new Thread(){
@Override
public void run()
{
while (true)
{
try
{
Thread.sleep(1500);
System.out.println(this.getName());
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}).start();

//这里的既复写Thread的run方法 又传入了Runnable子类 这时候会发生什么情况呢 ?

//这时候就需要看源码了:Thread类中有个Runnable对象,也就是构造方法传入的对象   Thread类的run方法会先判断时候有传入Runnable对象
//有的话就执行Runnable类的run方法  但是,这里复写了Thread的run方法,所以执行的时候就会执行子类复写过的run方法,所以这里就打印出
//From Runnable subClass!
//From this thread!

//super.run就是先调用负类的方法  如果去掉就不会打印出Runnable子类方法中的输出语句
new Thread(new Runnable()
{
@Override
public void run()
{
System.out.println("From Runnable subClass!");
}
}){
public void run() {
super.run();
System.out.println("From this thread!");
};
}.start();

}
}


4、线程的生命周期

创建:使用new运算符实例化一个线程对象,那么该线程对象就创建了。通过调用start()方法,可以启动该线程并且进入了就绪阶段。

就绪:就绪阶段可以分为两种情况:可运行状态(Runnable),正在运行状态(Running)。在任意一个时间片,只能有一个线程控制CPU。控制CPU的线程称为正在运行的线程,其他的线程称为可运行状态。

阻塞:处于阻塞状态的线程就失去了争抢CPU控制权的资格。阻塞状态又分为4种情况:休眠、等待、中断、挂起。

就绪休眠:sleep(n),经过n ms后该线程自动返回到就绪状态。

就绪挂起:suspend(),反过来使用resume()恢复该线程到就绪状态。这两对方法不推荐使用。

就绪中断:interrupt()方法,反过来,使用interrupted()方法。

就绪等待:wait()方法,反过来,使用notify()/notifyAll().

死亡:一个线程一旦运行完毕,即进行死亡状态,释放自身占用的资源。从死亡状态无法再返回到其他状态。

public class SuspendThread extends Thread {
//定义构造方法
public SuspendThread(String name)
{
super(name);
}
//线程 体
public void run()
{
System.out.println("线程体开始执行");
for(int i=0;i<1000000;i++)
{
double d = 10;
d = Double.MAX_VALUE/i+1;
}
for(int j=1;j<11;j++)
{
System.out.println(Thread.currentThread().getName() + "循环了" + j +"次");
if(j==5)
{
sleepThread(Thread.currentThread(),5000);
}
}
System.out.println("线程体执行完毕"); //死亡状态
}
public static void sleepThread(Thread t,long time)
{
if(t.isAlive())
try {
System.out.println("线程开始休眠");
t.sleep(time);
System.out.println("线程已醒,返回到就绪状态");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

/**
* 挂起一个线程t
* @param t
*/
@SuppressWarnings("deprecation")
public static  void suspendThread(Thread t)
{
//判断线程是否处于活动状态 ,指的就是就绪状态
if(t.isAlive())
{
t.suspend();

System.out.println("线程已挂起");
}
}
/**
* 恢复被挂起的线程
* @param t
*/
public static void resumeThread(Thread t)
{
if(!t.isInterrupted())
{
t.resume();
System.out.println("线程已恢复!");
}
}

public static void main(String args[])
{
SuspendThread st = new SuspendThread("A#");//创建状态
st.start();//就绪状态

//suspendThread(st);//阻塞状态 --挂起
//resumeThread(st);//将挂起的线程恢复,线程又重新进入了就绪状态
}
}


几个复杂的方法:
isAlive():是否处于活动状态,活动状态指的是从启动到死亡之间的时刻。
yield():一个正在运行的线程调用该方法后,失去CPU的控制权,重新和其他处于就绪状态的线程争抢CPU的控制权。

public class YieldThread extends Thread{
public YieldThread(String name)
{
super(name);
}
public void run()
{

for(int j=1;j<11;j++)
{
System.out.println(Thread.currentThread().getName() + "循环了" + j +"次");
if(j==3)
{
//让当前正在运行的线程放弃CPU的控制权
Thread.currentThread().yield();
}
}
}

public static void main(String[] args) {
for(int i=1;i<6;i++)
{
new YieldThread(i+"#").start();
}

}
}


join():让其他处于就绪状态的线程等待当前正在执行的线程。A正在执行B.join(long t)方法,B线程加入,其他线程待B执行完毕或者执行t毫秒后再执行。

public class JoinTest extends Thread{

/**
* @param args
*/
public static void main(String[] args) {
System.out.println(Thread.currentThread().getName());
JoinTest t1 = new JoinTest("T1");
JoinTest t3 = new JoinTest("T3");
JoinTest t2 = new JoinTest("T2");
t3.start();
t1.start();
t2.start();
try {
t2.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

public JoinTest(String name)
{
super(name);
}

public void run()
{
System.out.println(this.getName() + "线程开始执行,当前时间:" + System.currentTimeMillis());
for(int i=1;i<6;i++)
{
System.out.println(this.getName() + "循环体循环了" + i + "次");
}
System.out.println(this.getName() + "线程执行结束,当前时间:" + System.currentTimeMillis());
}
}


interrupt():中断一个线程。无论线程处于中断状态与否,isAlive()方法总是返回true.

interrupted():判断线程是否处于中断状态,如是中断状态返回true,并且将终止中断状态,返回到就绪状态。

isInterrupted():判断线程是否处于中断状态,如是中断状态返回true,否则false。并且当前线程的中断状态不会被清除。
public class SuspendThread extends Thread {
//定义构造方法
public SuspendThread(String name)
{
super(name);
}
//线程 体
public void run()
{
System.out.println("线程体开始执行");
for(int i=0;i<1000000;i++)
{
double d = 10;
d = Double.MAX_VALUE/i+1;
}
for(int j=1;j<11;j++)
{
System.out.println(Thread.currentThread().getName() + "循环了" + j +"次");
if(j==5)
{
//sleepThread(Thread.currentThread(),5000);
}
}
System.out.println("线程体执行完毕"); //死亡状态
}
public static void sleepThread(Thread t,long time)
{
if(t.isAlive())
try {
System.out.println("线程开始休眠");
t.sleep(time);
System.out.println("线程已醒,返回到就绪状态");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

/**
* 挂起一个线程t
* @param t
* @throws InterruptedException
*/
@SuppressWarnings("deprecation")
public static void suspendThread(Thread t)
{

//判断线程是否处于活动状态 ,指的就是创建状态到死亡之间时段
if(t.isAlive())
{
t.interrupt();
System.out.println("是否处于活动状态?" + t.isAlive());
System.out.println("线程已挂起");
}
}
/**
* 恢复被挂起的线程
* @param t
*/
public static void resumeThread(Thread t)
{
if(t.isInterrupted()) //true
{
t.interrupted(); //清除中断

System.out.println("线程已恢复!");
}
}

public static void main(String args[])
{
SuspendThread st = new SuspendThread("A#");//创建状态
st.start();//就绪状态

suspendThread(st);//阻塞状态 --挂起
resumeThread(st);//将挂起的线程恢复,线程又重新进入了就绪状态

}
}


5、线程的优先级

线程的优先级分为10个等级:1-10,1最低,10最高。Java的Thread类同时提供了3个常量表示优先级:MIN_PRIORITY (1), NORM_PRIORITY(5),MAX_PRIORITY(10),推荐为线程设置优先级时使用常量不要用数字。

线程的默认优先级是5
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: