线程
线程的创建
第一种创建线程的方式
继承Thread并重写run方法来定义线程要执行的任务。
第一种创建线程的方式有两个不足:
1:由于java是单继承,那么当继承了Thread后就无法再继承其他类。
2:由于继承Thread后重写run方法规定了线程执行的任务,这导致线程与任务有一个必然的耦合关系,不利于线程的重用。
class MyThread1 extends Thread{
public void run() {
for(int i=0;i<1000;i++) {
System.out.println("你是谁啊?");
}
}
}
class Mythread2 extends Thread{
public void run() {
for(int i=0;i<1000;i++) {
System.out.println("我是查水表的!");
}
}
}
public static void main(String[] args) {
Thread t1 = new MyThread1();
Thread t2 = new Mythread2();
/*
* 启动线程要指定start方法,而不是直接调用run方法。run方法是线程要执行的任务。
* 当线程的start方法被调用后,线程进入runnable状态,一旦获取CPU时间,run方法会自动被调用。
*/
t1.start();
t2.start();
}
第二种创建线程的方式
实现Runnable接口并重写run方法。
class MyRunnable1 implements Runnable{
public void run() {
for(int i=0;i<1000;i++) {
System.out.println("你是谁啊?");
}
}
}
class MyRunnable2 implements Runnable{
public void run() {
for(int i=0;i<1000;i++) {
System.out.println("我是查水表的!");
}
}
}
public static void main(String[] args) {
//单独定义任务
Runnable r1 = new MyRunnable1();
Runnable r2 = new MyRunnable2();
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
t1.start();
t2.start();
}
使用匿名内部类来完成方式一与方式二的线程创建
public static void main(String[] args) {
//方式一
Thread t1 = new Thread() {
public void run() {
for(int i=0;i<1000;i++) {
System.out.println("你是谁啊?");
}
}
};
t1.start();
//方式二
new Thread(new Runnable() {
public void run(){
for(int i=0;i<1000;i++) {
System.out.println("我是查水表的!");
}
}
}).start();
}
获取运行当前方法的线程
static Thread currentThread()
public static void main(String[] args) {
Thread main = Thread.currentThread();
System.out.println("运行main方法的线程是:"+main);
dosome();
Thread t = new Thread() {
public void run() {
Thread t = Thread.currentThread();
System.out.println("自定义线程:"+t);
dosome();
}
};
t.start();
}
public static void dosome() {
Thread t = Thread.currentThread();
System.out.println("运行dosome方法的线程是:"+t);
}
获取线程相关信息的方法
public static void main(String[] args) {
//获取运行main方法的线程
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);
}
结果:
id:1
name:main
优先级:5
是否存活:true
是否为守护线程:false
是否被中断:false
线程优先级
线程的时间片分配完全听线程调度的。
线程只能被动的被分配时间。对于线程调度的工作不能干预。
但是可以通过提高线程的优先级来达到尽可能干预的目的。
理论上,优先级越高的线程,获取CPU时间片的次数就越多。
public static void main(String[] args) {
Thread min = new Thread() {
public void run() {
for(int i=0;i<10000;i++) {
System.out.println("min");
}
}
};
Thread norm = new Thread() {
public void run() {
for(int i=0;i<10000;i++) {
System.out.println("nor");
}
}
};
Thread max = new Thread() {
public void run() {
for(int i=0;i<10000;i++) {
System.out.println("max");
}
}
};
min.setPriority(Thread.MIN_PRIORITY);
max.setPriority(Thread.MAX_PRIORITY);
min.start();
norm.start();
max.start();
}
守护线程
守护线程,又称为后台线程
当一个进程中的所有前台线程都结束时,进程就要结束,若还有后台进程运行,那么后台进程会被强制结束。
public static void main(String[] args) {
/*
* rose:前台线程
*/
Thread rose = new Thread() {
public void run() {
for(int i=0;i<10;i++) {
System.out.println("rose:let me go!");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("rose:啊啊啊啊啊啊啊AAAAAAAAAAAaaaaaaaaa");
System.out.println("音效:噗通!");
}
};
Thread jack = new Thread() {
public void run() {
while(true) {
System.out.println("jack:you jump!i jump!");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
//设置为后台进程,并且要在start前调用
jack.setDaemon(true);
rose.start();
jack.start();
// while(true);
}
void join()
join方法可以使调用该方法的线程进入阻塞状态,直到该方法所属线程完成工作才会解除调用该方法线程的阻塞状态。
join方法一般用来完成多个线程之间的同步工作问题。
//表示图片是否下载完毕
public static boolean isFinish = false;
public static void main(String[] args) {
final Thread download = new Thread() {
public void run() {
System.out.println("down:开始下载图片...");
for(int i=1;i<=100;i++) {
System.out.println("down:"+i+"%");
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("down:图片下载完毕!");
isFinish = true;
}
};
Thread show = new Thread() {
public void run() {
System.out.println("show:开始显示图片...");
/*
* 先等待download把图片下载完毕!
*/
try {
download.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
if(!isFinish) {
throw new RuntimeException("图片没有下载完毕!");
}
System.out.println("show:图片显示完毕");
}
};
download.start();
show.start();
}