+-
JAVA并发之多线程基础(1)

在JAVA中,谈到并发问题肯定是谈到多线程相关。可以说这两个之间有着一定的关系。在这里就为大家简单的说下多线程的基础,之后的文章中会继续讲解多线程相关。

什么是线程

线程是进程内的执行单元。一个进程中含有若干个线程,线程可以看做粒度更小的任务执行单元。进程之间切换,消耗的资源是很大的。通过线程去处理会很好的节省相关资源。

线程状态转化


... 线程状态转化


这上面是针对于线程的状态转化一个简单描述。这上面可以看到blocked的之间的状态只有一条线来回。这块的话关乎到`sychronized`的底层实现原理,大家可以自行了解下。这里面我就省略了一个Running的一个状态。Running的状态在可运行状态(Runnable)之后。

线程实现几种方式

继承Thread类 实现Runnable接口 实现Callable接口

上面是是实现线程的三种方式。在调用线程时候,调用的是其`start()`方法,而不是调用的`run()`方法。其中第三种实现方式结合`Future`可以获取到线程的返回值(同时,在线程池里面运行多线程的话,使用`exec.execute()`是拿不到线程执行的返回值,使用`exec.submit()`可以通过上面的`Future`取得线程执行的返回值)。

线程方法


`stop()`,这个方法使得当前所运行的线程停止,释放所有的monitor。但是使用这个方法会导致多线程的数据不一致性(假设两个线程执行中去停止,再次操作的时候,线程2有可能抢到原本线程1执行的步骤上)。 @Deprecated //提示过期方法 public final void stop() { //获取SecurityManager进行校验 SecurityManager security = System.getSecurityManager(); if (security != null) { checkAccess(); if (this != Thread.currentThread()) { security.checkPermission(SecurityConstants.STOP_THREAD_PERMISSION); } } if (threadStatus != 0) { // 如果线程被挂起,则唤醒线程;否则不执行任何操作 resume(); } // 调用系统方法去停止线程 stop0(new ThreadDeath()); }
`interrupt()`,这个方法会设置线程中断状态。是一个比较合理使用的一个方法。 public void interrupt() { if (this != Thread.currentThread()) checkAccess(); synchronized (blockerLock) {//加锁控制 Interruptible b = blocker; if (b != null) { interrupt0(); // 设置中断位 b.interrupt(this); return; } } interrupt0(); }


`interrupted()`判断当前线程是否被中断,并且清除当前线程中断状态。 public static boolean interrupted() { return currentThread().isInterrupted(true); } `sleep()`方法是让线程等待的。在大多数线程等待的方法中都会抛出`InterruptedException`异常。同时该方法不会释放锁以及所占用的资源。同时它会清除中断标志,所以在catch中再对该线程设置下中断标志。 public static native void sleep(long millis) throws InterruptedException; `suspend()`方法是让当前线程挂起,不会释放锁。 @Deprecated public final void suspend() { checkAccess(); suspend0(); }
`resume()`方法是让线程继续执行。使用这个的方法就有一个注意点,如果调用这个方法在`suspend`之前,那么线程就会永久的挂起,这个时候就会永久的占用了资源,可能会导致死锁的发生。 @Deprecated public final void resume() { checkAccess(); resume0(); } `join()`的主要作用就是同步,它可以使得线程之间的并行执行变为串行执行。 public final synchronized void join(long millis) throws InterruptedException { long base = System.currentTimeMillis(); long now = 0; if (millis < 0) { throw new IllegalArgumentException("timeout value is negative"); } if (millis == 0) { while (isAlive()) { wait(0); } } else { while (isAlive()) { long delay = millis - now; if (delay <= 0) { break; } wait(delay); now = System.currentTimeMillis() - base; } } }

这里面实际上调用的还是`Object`中的`wait()`方法。

这块也是对于当前使用最多的线程操作方法做了一个小的总结,在下一讲中我会谈及到JUC下面的各个锁操作。