1.线程中存在的现象
1.1线程加入public final void jion()
1.2线程礼让public static void yield()
1.3线程死亡a. public final void stop();直接结束线程,不再做任何操作
b. pubilc void interrupt();结束当前线程,并执行完相应的run()方法
使用代码对stop()和interrupt()进行测试:
import java.text.SimpleDateFormat;
import java.util.Date;
public class MyThread extends Thread{
@Override
public void run() {
//打印一下开始执行的时间
System.out.println("开始时间:"+new SimpleDateFormat("HH:mm:ss").format(new Date()));
//休眠10秒钟
try {
System.out.println(Thread.interrupted());
Thread.sleep(10000);
// this.interrupt();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
//e.printStackTrace();
System.out.println("我被杀死了");
}
System.out.println("结束时间:"+new SimpleDateFormat("HH:mm:ss").format(new Date()));
}
public static void main(String[] args) {
//创建线程对象
MyThread mt = new MyThread();
//开启线程对象
mt.start();
//在线程处于睡眠的过程中将他杀死
try {
Thread.sleep(3000);
//杀死刚刚开启的线程
//调用stop()方法将线程直接杀死
//mt.stop();//划了一条横线表示该方法已经过时,但是还可以使用
//interrupt():直接杀死,在死前,还可以有遗言。
mt.interrupt();//线程被杀死之后会将后面的代码执行完毕之后,再死去
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
2.线程周期
新建,就绪,运行,可能阻塞,死亡
3.线程间通信
以学生设置姓名和年龄为例演示线程通信问题
3.1需要用到的类
Student,SetThread,GetThread,Test
3.2如何使设置和获取线程操作同一对象
创建新的构造器,把资源作为构造参数传递下去
3.3使用同步唤醒机制实现线程礼让
3.4实现代码
public class Student {
//块编辑(alt+shift+a):在使用块编辑的时候,一定要将输入法切换到英文输入法,不然会出问题
private String name;
private int age;
private boolean flag;//在这里可以作为对象的一个标记,如果是false说明该对象没有数据,如果是true说明该对象有数据
//提供公共的方法设置信息
public synchronized void setInfo(String name,int age){
if (this.flag) {
//等待
try {
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//没有值的话,在这里给对象设置数据
this.name = name;
this.age = age;
//更改标记,唤醒获取线程获取数据
this.flag = true;
this.notify();
}
//提供公共的方法获取信息
public synchronized void getInfo(){
if (!this.flag) {
//没有值
try {
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//有数据,取数据
System.out.println(this.name+"--"+this.age);
//取完数据之后,就没有数据了
this.flag = false;
this.notify();
}
}
public class SetThread implements Runnable{
private Student s;
private int x = 0;
public SetThread(Student s){
this.s = s;
}
@Override
public void run() {
while (true) {
if (x%2==0) {
s.setInfo("刘嘉玲", 50);
}else {
s.setInfo("陈冠希", 35);
}
x++;//x=1
}
}
}
public class GetThread implements Runnable{
private Student s;
public GetThread(Student s){
this.s = s;
}
@Override
public void run() {
while (true) {
s.getInfo();
}
}
}
public class StudentDemo {
public static void main(String[] args) {
//创建学生对象
Student s = new Student();
//创建设置线程和获取线程
SetThread st = new SetThread(s);
GetThread gt = new GetThread(s);
Thread t1 = new Thread(st);
Thread t2 = new Thread(gt);
//开启线程
t1.start();
t2.start();
}
}
4.线程组
4.1定义:java使用ThreadGroup类来表示线程组,它可以对一批线程进行分类管理,java允许程序直接对线程组进行控制,表示一个线程的集合,线程组构成一棵树,在树中,除了初始线程组外,每个线程组都有一个父线程组。允许线程访问有关自己的线程组的信息,但是不允许它访问有关其线程组的父线程组或其他任何线程组的信息
4.2获取线程方法
public final ThreadGroup getThreadGroup();获取线程所在线程组
ThreadGroup(String name);创建新的线程组
5线程池
5.1为什么要使用线程池?
程序启动一个新线程成本是比较高的,因为它涉及到要与操作系统进行交互。而使用线程池可以很好的提高性能,
尤其是当程序中要创建大量生存期很短的线程时,更应该考虑使用线程池。
5.2线程池的特点:
线程池里的每一个线程代码结束后,并不会死亡,而是再次回到线程池中成为空闲状态,等待下一个对象来使用。
在JDK5之前,我们必须手动实现自己的线程池,从JDK5开始,Java内置支持线程池
5.3线程池如何创建?
JDK5新增了一个Executors工厂类来产生线程池,有如下几个方法
public static ExecutorService newFixedThreadPool(inneads)
5.4线程池使用步骤
1.创建线程池对象
ExecutorService pool = Executors.newFixedThreadPool(2);
2.创建Runnable实例
MyRunnable my = new MyRunnable();
3.提交Runnable实例
pool.submit(my);
pool.submit(my);
4.关闭线程池
pool.shutdown();
6.定时器Timer
一种工具,线程用其安排以后在后台线程中执行任务。可安排任务执行一次或定期重复执行。
重要方法:
int purgr();从计时器的任务列表中移除所有已取消的任务。
void schudle(Timer task, Date time);安排在指定的时间执行指定的任务