1.线程的概念
以往我们初级编程大多都是单线程的,即每次只有一条执行路径,但现实生活中很多过程都是可以多个途径一起执行的,并且现在的计算机都是支持多线程的,所以学会使用多线程能更好地提高计算机的运行效率,解决更多复杂问题哒。
注意:多任务和多线程是两个不同的概念!
多任务是针对操作系统而言,表示操作系统可以同时运营多个应用程序;多线程是针对一个进程而言,表示一个进程内部可以同时进行多个线程。
2.Thread线程类
Java实现多线程的方法有两种:一种是java.lang包中的Thread类,一种是实现Runnable接口,不管用哪种,都需要用到Thread类及其相关方法。
构造方法 | 功能说明 |
---|---|
public Thread() | 创建一个线程对象,此线程对象名字默认“Thread-n”,n是整数,使用这个构造方法,就必须创建一个Thread的子类,并覆盖其run方法 |
public Thread(String name) | name是线程名字 |
public Thread(Runnable target) | 线程名称还是默认“Thread-n”,target的run()方法被线程对象调用 |
public Thread(Runnable target,String name) | 功能同时,target的run()方法被线程对象调用,线程名字是name |
※ 第一次用,不太会排版! ?
方法名称 | 功能说明 |
---|---|
public static Thread currentThread() | 返回正在执行的线程对象 |
public final String getName() | 返回线程名称 |
public void start() | 使线程由新建状态变成就绪状态,若已是就绪状态,IllegalException异常 |
public void run() | 线程应执行的任务 |
public final void join() | 暂停当前线程的执行,等调用该方法的线程结束后再执行 |
public static void sleep(long millis) | 当前执行线程的睡眠时间,参数millis是毫秒数。若被中断,返回InterruptedException异常 |
public void interrupt() | 中断当前线程 |
※方法有很多,只列举了常用的一些。
实例
// filename:APP11_1.java
class MyThread extends Thread{
private String who;
public MyThread(String str){
who=str;
}
public void run(){
for(int i=1;i<=5;i++){
try{
sleep((int)(1000*Math.random()));
} //sleep()方法必须在try-catch语句块里
catch(InterruptedException e){ }
System.out.println(who+"正在运行!");
}
}
}
public class App11_1 {
public static void main(String[] args) {
MyThread t1=new MyThread("①");
MyThread t2=new MyThread("②");
t1.start();
t2.start();
System.out.println("主方法main运行结束!");
}
}
运行结果:
run:
主方法main运行结束!
①正在运行!
②正在运行!
②正在运行!
②正在运行!
①正在运行!
②正在运行!
②正在运行!
①正在运行!
①正在运行!
①正在运行!
成功构建 (总时间: 3 秒)
我们从运行结果可以看出两个线程t1,t2几乎同时激活,其实每次运行的结果都是不一样的,运行先后是随机的,看谁的睡眠时间更短一些。
我们注意到最后一行代码,预测它会是最后输出,却在第一行就输出了。事实上,main方法也是一个线程,它和t1,t2谁先输出,主要看谁能更快地抢到CPU资源。一般是main中语句先输出,因为它的线程没有激活过程。
2. 用Runnable接口创建线程
若类本身已继承了其他类,根据父类的唯一性,无法再继承Thread类,所以这时只好使用Runnable接口来实现线程的创建。
实例
// filename:APP11_2.java
class MyThread implements Runnable{
private String who;
public MyThread(String str){
who=str;
}
public void run(){
for(int i=1;i<=5;i++){
try{
Thread.sleep(1000);//睡眠时间设定为1秒
//注意这里,实现的是Runnable,而sleep()在Thread中
}
catch(InterruptedException e){ }
System.out.println(who+"正在运行!");
}
}
}
public class App11_2 {
public static void main(String[] args) {
MyThread one=new MyThread("①");
MyThread two=new MyThread("②");
Thread t1=new Thread(one);
Thread t2=new Thread(two);
//同理,创建Thread对象,调用start()方法
t1.start();
t2.start();
}
}
我们可以看出,Runnable接口中并没有任何对线程的支持,必须创建Thread类的实例,通过Thread的构造方法实现。
Runnable的好处不仅是解决了多重继承的问题,它更适用于多个线程解决同一资源的问题。事实上,几乎所有的多线程都可以用Runnable来实现。
附:join()方法的使用
//filename:App11_3.java
//此处复制App11_1中的MyThread类
public class App11_3 {
public static void main(String[] args){
MyThread one=new MyThread("①");
MyThread two=new MyThread("②");
one.start();
try{
one.join();
//限制直到one执行完毕后,才执行下一条命令
}
catch(InterruptedException e){ }
two.start();
try{
two.join();
//同理
}
catch(InterruptedException e){ }
System.out.println("主方法main()运行结束!");
}
}
运行结果:
run:
①正在运行!
①正在运行!
①正在运行!
①正在运行!
①正在运行!
②正在运行!
②正在运行!
②正在运行!
②正在运行!
②正在运行!
主方法main()运行结束!
成功构建 (总时间: 4 秒)
可见,join()可以限制线程的运行顺序。
哇,写一篇知识整理好累o(╥﹏╥)o
文中知识点皆来自我的课本《JAVA程序语言设计》?
若有写的不合理的地方请大家善意指出!