在java开发当中经常需要使用到并发编程,现在由浅入深,好好地看一下并发编程。这是并发编程的第一篇博客。太基本的不说了,直接看关键。
一、进程和线程的概念
进程:是系统进行资源分配和调度的一个单位。看起来很抽象,其实我们完全可以将其看成是一个exe。
线程:线程可以理解成进程中独立运行的子任务,比如说我们的QQ.exe在运行的时候,下载文件线程、好友视频线程等等也都在运行。
二、使用线程
线程有两种实现方式:
第一种:继承Thread类
public class MyThread extends Thread{
public void run(){
System.out.println(this.currentThread().getName()
}
}
第二种:实现Runnable接口
public class MyThread implements Runnable{
@override
public void run(){
System.out.println(this.currentThread().getName()
}
}
三、线程方法
1、currentThread
这个方法可以返回,当前的代码段是被哪一个线程调用的。下面看一个例子:
public class MyThread01 extends Thread{
@Override
public void run() {
System.out.println("run方法:"+Thread.currentThread().getName());
super.run();
}
public static void main(String[] args) {
MyThread01 thread=new MyThread01();
thread.start();
System.out.println("main方法:"+Thread.currentThread().getName());
}
}
看结果:
从结果可以看到,在main方法中执行的是main线程,在run方法中执行的是MyThread01
2、isAlive()方法
这个方法的作用是判断当前的线程是否处于活动状态。下面直接看例子
public class MyThread2 extends Thread{
@Override
public void run() {
System.out.println("run方法:"+this.isAlive());
}
public static void main(String[] args) {
MyThread01 thread=new MyThread01();
System.out.println("begin:"+thread.isAlive());
thread.start();
System.out.println("after:"+thread.isAlive());
}
}
看结果:
从上面的结果可以看到,一开始在start之前,没有处于活动状态,在start之后就变成了true
3、sleep()方法
这个方法的作用是在指定的毫秒数之内,让当前执行这个代码块的线程休眠。看例子如何使用
首先定义一个线程
public class MyThread2 extends Thread{
@Override
public void run() {
try {
System.out.println("run方法begin:"+System.currentTimeMillis());
//休眠两秒
Thread.sleep(2000);
System.out.println("run方法after:"+System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
然后再另外一个类中测试:
public class MyTest {
public static void main(String[] args) {
MyThread2 thread=new MyThread2();
System.out.println("begin:"+System.currentTimeMillis());
thread.start();
System.out.println("after:"+System.currentTimeMillis());
}
}
看结果
从上面的结果可以看到,run方法中begin和after相隔两秒执行
4、getId()方法
这个方法的作用是取得线程的唯一标识。举例子,在上面MyThread2的基础之上,对MyTest进行修改。
public class MyTest {
public static void main(String[] args) {
MyThread2 thread=new MyThread2();
thread.start();
System.out.println("MyThread2得Id:"+thread.getId());
}
}
看结果:
5、yield方法
这个方法的作用是放弃当前的CPU资源,将他让给其他的任务去执行,但是放弃的时间不确定,有可能刚刚放弃,马上又获得CPU。下面举例子说明:
首先定义线程
public class MyThread3 extends Thread{
@Override
public void run() {
long beginTime=System.currentTimeMillis();
int count=0;
for(int i=0;i<500000;i++) {
count=count+i;
}
long endTime=System.currentTimeMillis();
System.out.println("一共用时:"+(endTime-beginTime)+"毫秒");
}
}
然后修改测试类:
public class MyTest {
public static void main(String[] args) {
MyThread3 thread=new MyThread3();
thread.start();
}
}
现在没有使用yield的时候,就会一直执行for循环,此时是非常快的,因为CPU执行的快,看结果
现在使用yield方法。在for循环里面添加这个方法
for(int i=0;i<500000;i++) {
Thread.yield();
count=count+i;
}
此时再看结果:
6、停止线程
停止线程可以使用如下的方法。
- this.interrupted():测试当前运行this.interrupted代码的线程是否是中断状态,执行后具有将状态标志清楚为false的功能。
- this.isInterrupted():测试线程Thread对象是否已经是中断状态,但不能清除状态标志
下面举例子说明看看如何停止线程:
public class MyThread3 extends Thread{
@Override
public void run() {
for(int i=0;i<500000;i++) {
//判断当前的MyThread3是否是终止状态
if(this.interrupted()) {
System.out.println("已经是停止状态,退出:"+this.interrupted());
break;
}
System.out.println("i= "+i);
}
System.out.println("for循环之后的语句");
}
}
然后是测试类
public class MyTest {
public static void main(String[] args) throws InterruptedException {
MyThread3 thread=new MyThread3();
thread.start();
//在这里休眠的作用是中间输出一部分count,不至于刚刚启动就终止了
Thread.sleep(1000);
thread.interrupt();
}
}
最后看结果:
从上面的结果可以看到的确终止了,但是for循环之后的语句还会执行,如果想要完全的中断线程,该怎么办呢?
public class MyThread3 extends Thread{
@Override
public void run() {
try {
for(int i=0;i<500000;i++) {
//判断当前的MyThread3是否是终止状态
if(this.interrupted()) {
System.out.println("已经是停止状态,退出:"+this.interrupted());
throw new InterruptedException();
}
System.out.println("i= "+i);
}
System.out.println("for循环之后的语句 ");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
此时只需要把break换成抛出中断异常的代码即可。此时测试类不变,再测试一下
从上面的即如果可以看到,被强制退出,然后for循环之后的语句也没有继续执行。
当然也可以把break语句换成return,依然可以起到中断线程的作用。
好了,线程基础知识先说到这。