线程创建的三种方式
第一种创建线程的方式
继承Thread类并重写run方法来定义线程要执行的任务
class MyThread extends Thread{
public void run(){
for(int i=0;i<1000;i++){
System.out.println("你好啊!");
}
}
}
第一种创建线程的方式有两个不足:
1:由于java是单继承,那么当继承了Thread后就无法再继承其他类.
2:由于继承Thread后重写run方法规定了线程执行的任务,这导致线程与任务有一个必然的耦合关系,不利于线程的重用.
第二种创建线程的方式
实现Runnable接口并重写run方法.
class MyRunnable implements Runnable{
public void run(){
for(int i=0;i<1000;i++){
System.out.println("你好啊");
}
}
}
第三种创建线程的方式
FutureTask<Boolean> futureTask = new FutureTask<Boolean>(new Callable() {
@Override
public Boolean call() throws Exception {
return new File("111.txt").exists();
}
});
Thread t2 = new Thread(futureTask);
t2.start();
try {
//返回结果,最长等待5S
Boolean b = futureTask.get(5,TimeUnit.SECONDS);
} catch (InterruptedException e) {
//中断
e.printStackTrace();
} catch (ExecutionException e) {
//停止
e.printStackTrace();
} catch (TimeoutException e) {
//超时
e.printStackTrace();
}
类似于Runnable,实现Callable接口,实现call方法,创建线程,通过FutureTask获取返回结果,此方式可以获取线程返回值。
线程启动
启动线程要指定start方法,而不是直接调用run方法.run方法是线程要执行的任务.当线程的start方法被调用后,线程进入runnable状态,一旦获取cpu时间,run方法会自动被调用.
public class ThreadDemo {
public static void main(String[] args) {
Thread t1 = new MyThread();
t1.start();
Runnable r = new MyRunnable();
Thread t2 = new Thread(r);
t2.start();
}
}
获取线程信息
public static void main(String[] args) {
Thread main = Thread.currentThread(); //获取当前线程
long id = main.getId();
System.out.println("id:"+id);
String name = main.getName();
System.out.println("name:"+name);
int priority = main.getPriority();
System.out.println("优先级:"+priority);
boolean isAlive = main.isAlive();
System.out.println("是否存活:"+isAlive);
boolean isDaemon = main.isDaemon();
System.out.println("是否为守护线程:"+isDaemon);
boolean isInterrupted = main.isInterrupted();
System.out.println("是否被中断:"+isInterrupted);
}
线程优先级
线程的时间片分配完全听线程调度的,线程只能被动的被分配时间,对于线程调度的工作不能干预,但是可以通过提高线程的优先级来达到尽可能干预的目的。理论上,优先级越高的线程,获取CPU时间片的次数就越多。
守护线程
又称为后台线程。当一个进程中的所有前台线程都结束时,进程就要结束,若还有后台线程运行,那么后台线程会被强制结束。
Thread t1 = new MyThread();
t1.setDaemon(true); //设置为后台线程,并且要在start前调用
t1.start();
线程阻塞
线程提供的静态方法sleep(long ms)可以使运行该方法的线程进入阻塞状态指定毫秒。超时后线程会自动回到runnable状态。
join()方法可以使调用该方法的线程进入阻塞状态,直到该方法所属线程完成工作才会解除调用该方法线程的阻塞状态。
public static void main(String[] args) {
Thread t1 = new Thread(){
public void run(){
try{
Thread.sleep(5000); //阻塞5s
}catch(InterruptedException e){
}
System.out.println("t1执行完毕!");
}
};
Thread t2 = new Thread(){
public void run(){
try{
t1.join(); //等待t1执行完毕
}catch(InterruptedException e){
}
System.out.println("t2执行完毕!");
}
};
t1.start();
t2.start();
}
join方法一般用来完成多个线程之间的同步工作问题。