- 线程的常用方法
public final void join() 线程加入
作用:等待该线程中止,其他线程才能继续抢着执行
public static void yield(): 线程礼让
作用:暂停当前正在执行的线程对象,并执行其他线程。让线程间的执行更和谐一些,但是实际上做不到。
public final void stop():线程死亡:直接杀死
public void interrupt():线程死亡:直接杀死,在死前,还可以有遗言(会执行后面的代码,然后死去)。
static void sleep(long millis) 线程休眠:线程睡一会,会自己醒来
2.线程的生命周期
a.新建:创建一个线程对象
b.就绪:start()之后,有cpu的执行权,但没有抢到执行资格
c.运行:有cpu的执行权,也有cpu的执行资格
d.有可能阻塞:休眠或者等待
e.死亡:run()方法执行完毕,调用stop()或者interrup()方法
生命周期图如下:
3.线程间通信
定义:不同线程间针对同一个资源进行操作
Student -- 被设置的资源对应的类
setThread -- 设置线程
getThread -- 获取线程
StudnetDemo -- 测试类
public class Student {
private String name;
private int age;
//作为对象的一个标记,如果是false说明该对象没有数据
private boolean flag;
//提供公共的方法设置信息
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 GetThread implements Runnable{
private Student s;
public GetThread(Student s){
this.s = s;
}
@Override
public void run() {
//获取线程,获取学生对象的姓名和年龄
while (true) {
s.getInfo();
}
}
}
}
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.name = "周杰伦";
s.age = 40;
}else {
s.name = "林宥嘉";
s.age = 30;
}
x++;
}
}
}
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.线程组
定义:Java中使用ThreadGroup来表示线程组,它可以对一批线程进行分类管理,Java允许程序直接对线程组进行控制。默认情况下,所有的线程都属于主线程组。
主要方法:
public final ThreadGroup getThreadGroup():获取线程对应的线程组对象
Thread(ThreadGroup group, Runnable target):线程设置分组
案例1:创建线程获取对应的线程组对象,并获取名称
//创建两个线程
MyThread mt1 = new MyThread();
MyThread mt2 = new MyThread();
//获取上面两个线程对应的线程组对象
ThreadGroup tg1 = mt1.getThreadGroup();
ThreadGroup tg2 = mt2.getThreadGroup();
//获取线程组对象的名称
System.out.println(tg1.getName());
System.out.println(tg2.getName());
案例2:创建线程组对象,给线程分配线程组
ThreadGroup tg = new ThreadGroup("big");
Thread t3 = new Thread(tg, new MyRunnable());
Thread t4 = new Thread(tg, new MyRunnable());
//获取t3和t4的线程组对象
ThreadGroup tg3 = t3.getThreadGroup();
ThreadGroup tg4 = t4.getThreadGroup();
System.out.println(tg3.getName());
System.out.println(tg4.getName());
5.线程池
引入原因:程序启动一个新线程成本是比较高的,因为它涉及到要与操作系统进行交互。而使用线程池可以很好的提高性能,尤其是当程序中要创建大量生存期很短的线程时,更应该考虑使用线程池。
特点:线程池里的每一个线程代码结束后,并不会死亡,而是再次回到线程池中成为空闲状态,等待下一个对象来使用。
线程池的创建方法:
public static ExecutorService newFixedThreadPool(int nThreads)
线程池的使用步骤:
a.创建线程池对象
ExecutorService pool = Executors.newFixedThreadPool(2);
b.创建Runnable实例
MyRunnable my = new MyRunnable();
c.提交Runnable实例
pool.submit(my);
pool.submit(my);
d.关闭线程池
pool.shutdown();
6.定时器(Timer):
主要方法:
public Timer()构造
public void schedule(TimerTask task, long delay)延迟多久执行任务
public void schedule(TimerTask task,long delay,long period)延迟多久执行任务,并以后每隔多久执行一次
public boolean cancel()取消这个任务
TimerTask
public abstract void run()放的是所要执行的任务代码
案例:延迟5秒钟,打印hellojava,以后每隔一秒打印一次
public static void main(String[] args) {
Timer t = new Timer();
t.schedule(new MyTimerTask2(), 5000, 1000);
/**
* 参数1:要执行的任务
* 参数2:延迟多久执行
* 参数3:执行一次之后,每隔多久重复执行
*/
}
}
class MyTimerTask2 extends TimerTask{
@Override
public void run() {
System.out.println("hellojava");
}
}