您的位置:首页 > 编程语言 > Java开发

多线程基础学习一:Thread基础学习

2017-08-31 18:06 218 查看
最近开始学习多线程的基础知识,以学习使用为主。

创建一个线程

Thread是一个实现了Runnable接口的实现类,所以创建线程只要集成重写run方法就可以了。

/**
* Created by nyl
* 2017/9/15 0015
*/
public class DaemonTest {

public static void main (String[] args) {

Thread thread = new MyThread();
//thread.setDaemon(true);
thread.start();
System.out.println("main主线程结束");
}

private static class MyThread extends Thread{

@Override
public void run () {
int i = 0;
while(i <= 10) {
try {
Thread.sleep(1000);
i++;
System.out.println("执行第" + i  + "次");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println("我出现异常了");
}
}

}
}
}


启动线程的方法是start方法,看到网上经常有人问run() 和start()方法区别,自己也尝试了一下,其实run方法,只是实例化了一个对象,调用了对象的一个方法,没有创建新线程,start方法则创建了新线程。

调用start方法执行结果:

main主线程结束
执行第1次
执行第2次
执行第3次
执行第4次
执行第5次
执行第6次
执行第7次
执行第8次
执行第9次
执行第10次
执行第11次


可以看到一开始就是main主线程结束了,然后才是新线程执行的结果,如果调用run方法,结果如下:

执行第2次
执行第3次
执行第4次
执行第5次
执行第6次
执行第7次
执行第8次
执行第9次
执行第10次
执行第11次
执行第12次
main主线程结束


可以看到,先把run方法执行完,才输出了main线程结束,其实run方法和普通方法调用一样,调用一次执行一次。

网上看到关于守护线程daemon的内容,如果java虚拟机没有非守护线程,就会退出,测试了一下:

设置(默认false)

thread.setDaemon(true);


执行结果

main主线程结束


结果只输出了这一句话,看来线程还没执行虚拟机就退出了。但是我注意到,并没有输出“我出现异常了”这句话,一般finally都会执行,看来这种情况finally不执行了。

常用方法

等待一段时间继续执行

sleep(毫秒数),这个方法是Thread的类方法,它的注释是这么写的:

如果任何线程中断了当前线程。当抛出此异常时,当前线程的中断状态被清除。


首先,sleep方法并没释放锁,当前线程会休眠指定的时间,调用方式一般是这样的:

Thread.sleep(1000);


在哪个线程里写,哪个线程就会休眠执行指定时间。还有另外一种写法,是这样的:

Thread.currentThread().sleep(1000);


个人觉得多此一举,完全没有必要这么写。

还有一些有特殊意义的写法,比如sleep(0) ,sleep(1),目前还不清楚它们的意义。

测试代码:

/**
* Created by nyl
* 2017/9/15 0015
*/
public class DaemonTest {

public static void main (String[] args) {

Thread thread = new MyThread();
//thread.setDaemon(true);
thread.start();

System.out.println("main主线程结束");
try {
//thread.stop();
Thread.sleep(5000);
System.out.println("等待5s结束");
} catch (InterruptedException e) {
e.printStackTrace();
}
}

private static class MyThread extends Thread{

@Override
public void run () {
int i = 0;
while(i <= 10) {
try {
Thread.sleep(1000);
i++;
System.out.println("执行第" + (i + 1) + "次");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
//System.out.println("我出现异常了");
}
}

}
}

}


输出结果:

执行第2次
执行第3次
执行第4次
执行第5次
执行第6次
等待5s结束
执行第7次
执行第8次
执行第9次
执行第10次
执行第11次
执行第12次


可以看到,主线程等待了5秒,新线程没有受影响。

暂停与恢复

suspend() 是暂停方法, resume()是恢复方法,两个都是对象方法,测试代码如下:

public class PasueTest {

public static void main (String[] args) {

Thread thread = new MyThread();
thread.start();

System.out.println("main主线程结束");
try {
thread.suspend();
Thread.sleep(5000);
System.out.println("等待5s结束");
System.out.println("暂停执行5s");
thread.resume();
System.out.println("恢复重新执行");
} catch (InterruptedException e) {
e.printStackTrace();
}
}

private static class MyThread extends Thread{

@Override
public void run () {
System.out.println("我执行了");
}
}
}


执行出现了两中结果,第一种:

main主线程结束
等待5s结束
暂停执行5s
恢复重新执行
我执行了


第二种:

main主线程结束


一直卡在那了

不知道第二种情况为什么会出现,总而言之这两个方法已经过时了,还有其它方面的问题,不要再用了。

终结线程

终止线程有五个方法,分别为stop()、cancle() (Runnable)、 interrupt()(抛出异常或者自己处理)以及标志位结束,其中stop方法已经过期,这个方法不会释放资源。

cancle方法的使用:

public class CancleTest {

public static void main (String[] args) {

Thread first = new Thread(new CancleThread());
first.setDaemon(true);
first.start();
SleepUtil.sleep(5000);
System.out.println("线程取消了");
}

static class CancleThread implements Runnable {

@Override
public void run () {

while (true) {
SleepUtil.sleep(1000);
System.out.println("我执行了");
}
}
}
}


执行结果:

我执行了
我执行了
我执行了
我执行了
我执行了
线程取消了


interrupt()(抛出异常或者自己处理):

public class InterruptedTest {

public static void main (String[] args) {

Thread first = new InterruptedThread();
first.setDaemon(true);
Thread second = new Interrupted1Thread();
second.setDaemon(true);
first.start();
second.start();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
first.interrupt();
System.out.println("first interrupt is " + first.isInterrupted());

SleepUtil.sleep(50);
}

static class InterruptedThread extends Thread {

@Override
public void run () {
while (true) {
try {
Thread.sleep(1000);
System.out.println("中断状态是:" + Thread.interrupted());
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}


执行结果:

中断状态是:false
中断状态是:false
中断状态是:false
中断状态是:false
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at learn.threadlearn.InterruptedTest$InterruptedThread.run(InterruptedTest.java:40)
中断状态是:false
first interrupt is true


抛出了InterruptedException异常(finally会被执行),这个异常抛出时,会清除中断状态.

标志位结束:

public class FlagTest {

private static boolean type = true; // 标志位, 这样写不严谨,有风险

public static void main (String[] args) {

FlagThread  first = new FlagThread();
first.setDaemon(true);
first.start();
SleepUtil.sleep(5000);
type = false;
SleepUtil.sleep(2000);
}

static class FlagThread extends  Thread {

@Override
public void run () {
while (type) {
SleepUtil.sleep(1000);
System.out.println("正在执行");
}

System.out.println("执行结束了");
}
}

}


执行结束:

正在执行
正在执行
正在执行
正在执行
正在执行
执行结束了


以上集中方式都可以结束线程。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  多线程 java