线程操作类

2020-09-23 10:37:26 浏览数 (1)

线程操作类:

线程操作类是Thread类,可以使用这个类进行线程方面的相关操作,例如获得当前线程对象,令当前睡眠,强制激活线程等等,可以直接调用静态的方法。

如何获得当前线程:

currentThread();是获得当前线程对象的方法,可以直接使用也可以将得到的对象存放到变量中,得到对象后还可以使用getName();方法得到线程对象的名称,还有getId();方法可以得到线程对象的编号,getPriority();方法则可以可以得到线程对象的优先级。

代码示例:

运行结果:

如何使线程在某个地方就结束呢:

stop();方法,从名字也看的出来,这方法就是调用后会终止线程的,这个方法会直接把线程对象销毁,来起到结束线程。一旦线程结束了,接下来的代码就不会被执行,不管是什么代码,还有需要注意的一点是:线程只有一次生命,结束之后等于死亡状态,这个“死掉”的线程是不可以再复活的,所以没有办法再继续启动的。

代码示例:

运行结果:

从结果可以看出,线程结束后的两句打印函数没有被执行

认识一下线程的状态:

State是枚举类型,使用这个类可以得到所有状态,要注意的是并不是得到某个线程对象的状态,想要得到某个线程的状态要使用那个线程对象调用getState();方法获得。

   Thread.State.NEW  新建状态

当线程对象刚刚被创建,还没有进入运行、开启的时候就是新建状态。

Thread.State.RUNNABLE 运行状态

当线程对象进入运行、开启的时候就是运行状态。

Thread.State.WAITING  无时间限制等待状态

当线程对象调用wait方法时,并且没有设置时间参数时就会进入此状态。

Thread.State.TIMED_WAITING  有时间限制的等待状态

当线程对象调用sleep方法时,并且设置时间参数后就会进入此状态。

Thread.State.TERMINATED   线程死亡状态

线程对象被销毁,线程结束时就会进入死亡状态。

Thread.State.BLOCKED  线程死锁状态

在线程同步里,两个线程陷入互相等待对方的时候就会进入线程死锁状态。

如何开启一个线程:

想要开启一个线程,首先要写一个类继承于Thread类,并且要重写run();方法,然后创建线程对象后使用对象调用start();方法来启动线程。

为什么一定要重写run();方法呢,因为线程对象在调用start方法的时候会向系统申请资源,接着线程就会进入到运行状态,线程进入到运行状态的时候会调用run方法,run方法结束后线程就会进入死亡状态。线程进入运行状态时首先调用的是run方法,做个不是很恰当的比喻就是:run方法就类似于普通类的main方法一样,运行时实际上只会执行这个方法里面的代码。所以你想要线程执行你编写的代码就必须重写run方法。

当你想给线程起一个你想出来的名字可以使用线程对象调用setName方法来设置线程的名字。

代码示例:

运行结果:

从代码的运行结果来看,有人可能会疑惑为什么main方法里的打印函数明明在最后一句,为什么会先执行?

实际上呢,问题不在于谁先执行了,首先main也是一个线程,你开启的也是一个线程,线程之间是独立并行的,至于谁的代码先执行完是要看谁跑的快,就像食堂开饭一样,先到的先打到饭后到的后打到饭,所以也是会出现main线程后面才执行完的情况的。

线程这货可不止继承Thread类这一种创建方式,线程还可以实现Runnable这个接口来创建。至于为什么还有这种创建方式,因为别忘了java只能单一继承,万一继承了其他的类又要把这个类作为线程的时候就只能使用接口的方式了,而且接口也能多实现多个。

  代码示例:

运行结果:

可能看到代码后,又有人会疑惑,为什么构建Thread类的时候需要将当前的类的实例对象传递给Thread的构造器?

因为在Thread的内核代码里的原理是这样的:

也就是说,你将对象传递过去后,这个类会将这个对象经过一系列的处理后保存到这个Thread类的属性里,所以当你在你写的类中使用Thread的对象调用run方法的时候就又会调回到你原来的类上面去,简单的理解就是调用run的时候在里面浪了一圈之后就回到你写的run方法上去了。

sleep方法:

sleep方法可以设置一个时间使线程进入睡眠状态,线程进入睡眠状态后会根据你设置的时间参数醒来。使用sleep时要知道的一点是:sleep方法是静态的,在当前的线程下不能使用这个方法来让另一个线程进入睡眠状态。

例如:A线程不能在自己的线程里使用B线程的对象来调用sleep方法,因为即便是使用B线程的对象来调用了也是A线程会进入睡眠状态并不是B线程。所以由此可知在哪个线程里遇到sleep方法哪个线程就会进入睡眠状态,即便你使用的是其他线程对象调用的也是如此。

还有一点就是:调用sleep方法线程进入睡眠状态后,如果这个线程被强制激活、叫醒了,就会抛出异常。因为你想想睡着睡着被叫醒,是个人都有起床气嘛,呸,说错了不是人是线程,但是睡到自然醒就不会有这个问题。

当线程对象进入睡眠状态,你想要在代码运行到某处的时候叫醒睡眠中的线程的话,可以使用睡眠中的线程对象调用interrupt();方法,此方法可以强制激活睡眠中的线程,但是这种激活方式就如同上面所说的会抛出异常,需要注意处理异常;

激活线程代码示例:

运行结果:

不激活线程代码示例:

运行结果:

主线程和子线程:

主线程是开启某个线程的线程,被这个线程开启的线程就是子线程。这个说法说起来有点绕口,换个比喻就是:例如main是一个线程,在main里开启了一个A线程,那么main就是主线程A就是子线程。

主线程会等待子线程结束才结束,也就是说子线程还有一秒没干完活,主线程就不会自己偷跑。

但是有个方法可以让主线程结束的时候就把子线程结束掉,称之为守护型线程,只要主线程结束,不管子线程是否还有代码没有执行完都强制随着主线程结束,这个方法就是setDaemon(boolean on); 使用线程对象调用此方法时给参数传递个true就代表这是个守护型线程,要注意的是这个方法一定要在start方法之前调用,在start方法之后调用是会抛异常的,因为你得在线程启动前声明这是个守护型线程。

  代码示例:

运行结果:

因为主线程先结束了,子线里的循环还没来得及进行,所以count的值为0。

join方法:

此方法的作用是等待线程结束,一般在书面上写的意思是合并线程方法,从其作用来理解成等待线程结束会好理解一些,只有等待到线程结束了,才会执行下面的代码。

这个方法可以传递一个时间参数,用来表示如果线程到指定的时间还没结束就不等了,就会继续执行下面的代码。如果不设置时间参数的话,就会一直死等到线程结束为止,才会往下执行。

  不设置时间参数的代码示例:

运行结果:

设置时间参数的代码示例:

运行结果:

使用线程优化之前的代码统计器的统计代码的速度:

线程类:

文件搜索类:

每找到一个文件就开启一个线程去统计

运行结果:

0 人点赞