1、引入线程的优点:
1)充分利用cup资源
2)简化编程模型
3)简化异步事件处理
4)使GUI更有效率
5)节约成本
2、线程使用:在Java中创建线程有几种方法,每个Java程序至少包含一个线程:主线程。其他线程都是通过Thread构造器或者实例化继承类Thread的类来创建的。
比如通过Thread类获取程序的主线程
public class test {
public static void main(String[] args) {
// TODO Auto-generated method stub
Thread t=Thread.currentThread();
System.out.println(t);
}
}
运行结果如下:
(1)创建线程
在Java中创建线程有两种方法:使用Thread类和使用Runnable接口,在使用Runnable接口时需要建立一个Thread实例 ,因此,无论是通过Thread类还是通过Runnable接口建立线程,都必须建立Thread类或者他的子类的实例。
1)Thread:子类需重写run方法,并在run方法内部定义线程的功能语句。
class Thread1 extends Thread{
public void run() {
System.out.println(Thread.currentThread().getName());
}
}
class Thread2 extends Thread{
public Thread2(String string) {
super(string); //重写父类方法
}
public void run() {
System.out.println(Thread.currentThread().getName());
}
}
public class test {
public static void main(String[] args) {
Thread1 t1=new Thread1();//未指定线程名,输出的线程名是系统默认值
Thread2 t2=new Thread2("Thread2");//构造名为Thread2的线程对象
t1.start();//start()方法不能多次调用,否则会报错
t2.start();
System.out.println(Thread.currentThread().getName());
}
}
可能的运行结果如下,对于输出结果而言, 不仅不同机器之间的结果可能不同,而且在同一机器上多次运行同一程序也可能生成不同结果,另外,线程的执行次序是不定的,除非使用同步机制以强制按特定的顺序执行。
2)Runnable:实现runnable接口的类必须使用Thread类的实例才能创建线程,通过Runnable接口创建线程的步骤如下:
①实例化实现runnable接口的类
②建立一个thread对象,并将第一步实例化后的对象作为参数传入thread类的构造方法
③通过thread类的start()方法建立线程
package javase;
class Thread1 extends Thread{
public void run() {
System.out.println(Thread.currentThread().getName());
}
}
class Thread2 extends Thread{
public Thread2(String string) {
super(string); //重写父类方法
}
public void run() {
System.out.println(Thread.currentThread().getName());
}
}
class Thread3 implements Runnable{
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println(Thread.currentThread().getName());
}
}
public class test {
public static void main(String[] args) {
Thread1 t1=new Thread1();//未指定线程名,输出的线程名是系统默认值
Thread2 t2=new Thread2("Thread2");//构造名为Thread2的线程对象
t1.start();//start()方法不能多次调用,否则会报错
t2.start();
Thread3 t3=new Thread3();
Thread t=new Thread(t3);//将实现Runnable的类的实例传入构造函数
t.start();
System.out.println(Thread.currentThread().getName());
}
}
可能的运行结果为:
(2)线程的状态
线程的状态分为7种:born(新生状态)、runnable(就绪状态)、running(运行状态)、waiting(等待状态)、sleeping(睡眠状态)、blocked(阻塞状态)、dead(死亡状态)
1)born:当使用new来创建一个线程时,一个新的线程就诞生了
2)runnable和running
把处理器分配给一个处于runnable的线程后,这个线程的状态就变成running。可以通过Thread类的isAlive()方法来判断线程是否处于运行状态,下面这个代码是创建、运行和停止三个状态之间的切换
class Thread1 extends Thread{
public void run() {
}
}
public class test {
public static void main(String[] args) throws Exception{
Thread1 t1=new Thread1();//未指定线程名,输出的线程名是系统默认值
System.out.println("等待状态 "+t1.isAlive());
t1.start();//start()方法不能多次调用,否则会报错
System.out.println("运行状态 "+t1.isAlive());
t1.join();
System.out.println("结束状态 "+t1.isAlive());
}
}
运行结果为:
3)blocking:在线程试图执行某个不能立即完成的任务,并且该线程必须等待其他任务的完成时才能继续,则该线程进入阻塞状态
4)sleeping:在线程执行的过程中,可以通过sleep方法使线程暂时停止执行,使其进入sleep状态
package javase;
class Thread1 extends Thread{
boolean flag=true;//退出安全控制位
public void run() {
while(flag) {
System.out.println("TimeThread");
try {
Thread.sleep(1000);//休眠1秒
}catch(Exception e){
System.out.println(e);
}
}
}
public void safeStop() {
flag=false;
}
}
public class test {
public static void main(String[] args) {
Thread1 t1=new Thread1();//未指定线程名,输出的线程名是系统默认值
t1.start();
try {
//等待主线程键盘输入
System.in.read();
t1.safeStop();
}catch(Exception e) {
System.out.println(e);
}
}
}
上述代码运行期间会每秒输出Time Thread,直到用户在主线程环境下按下键盘键
注:如果一个线程包含很长的循环,在循环的每次迭代之后把这个线程切换到sleep状态是一个很好的策略,这可以保证其他线程不必等很长时间才轮到处理器执行。
5)waiting:如果某个线程执行条件还未满足,可以调用wait方法使其进入等待状态。
- dead:线程运行到run()方法的结尾或线程抛出一个未捕获异常或Error,或使用interrupt()方法中断线程
package javase;
class Thread1 extends Thread{
public void run() {
try {
System.out.println("在20秒内按回车键结束线程");
Thread.sleep(20000);
}catch(Exception e) {
System.out.println(e);
}
}
}
public class test {
public static void main(String[] args) throws Exception {
Thread1 t1=new Thread1();//未指定线程名,输出的线程名是系统默认值
t1.start();
System.in.read();
t1.interrupt();
t1.join();
System.out.println("线程退出");
}
}
版权归原作者 朱颜辞镜花辞树> 所有, 如有侵权,请联系我们删除。