java线程整理(一)

java线程整理(一)

 

线程与进程的概念

进程就是在某种程度上相互隔离的、独立运行的程序,拥有并分配系统资源。

线程(thread),有时被称为轻量级进程(Lightweight ProcessLWP),是程序执行流的最小单元。

线程在程序中是独立的、并发的执行路径,每个线程有它自己的堆栈、自己的程序计数器和自己的局部变量。但它们它们共享内存、文件句柄和每个进程应有的状态。

一个进程中可以包含若干个线程。

 

为什么使用线程

  线程比进程更小,基本上不拥有系统资源,故对它的调度所付出的开销就会小得多,能更高效的提高系统内多个程序间并发执行的程度,从而显著提高系统资源的利用率和吞吐量。

 · 利用多处理器系统

 · 简化建模

 · 执行异步或后台处理

Java线程的常用的API

建议使用的方法

方法

说明

start

start()方法就是启动线程的方法,这个方法是线程类中最核心的方法。当调用这个方法以后,它就会启动线程,并让线程去执行指定的方法,而这里说的指定的方法,就是下个要说的run()方法。如果这个线程已经开始执行,再次调用该方法,则会抛出IllegalThreadStateException异常。

run

start()方法会将它作为线程的起点,线程执行的业务逻辑应该在这里实现。

并且run() 的访问控制符必须是public,返回值必须是voidrun()不带参数。

sleep

sleep()方法是一个静态方法,让当前线程挂起。如果当前线程已经被别的线程中断的话,将会抛出InterruptedException异常,而且interrupted标志也会被清空。

join

保证当前线程停止执行,直到该线程所加入的线程完成为止。如果当前线程已经被别的线程中断的话,将会抛出InterruptedException异常,而且interrupted标志也会被清空。

yield

yield()使当前线程临时的中断执行,并让当前运行线程回到可运行状态,以允许具有相同优先级的其他线程获得运行机会使用yield()的目的是让相同优先级的线程之间能适当的轮转执行。但是,实际中无法保证yield()达到让步目的,因为让

步的线程还有可能被线程调度程序再次选中。JAVA线程模型实际上映射到操作系统的线程模型,所以对于不同的操作系统,这个方法的就有不同的意义。对于非抢占式Operating System,这个方法使得其他线程得到运行的机会,但是对于抢占式的OS,这个方法没有太多的意义。

wait

Wait方法和后边的两个方法都来自Object。这个方法的作用是让当前线程等待,直到被唤醒或者等待的时间结束。当前线程进入等待队列的时候,会放弃当前所有的资源,所以当前线程必须获得这些对象的Monitor,否则会扔出IllegalMonitorStateException

notify

通知其他线程可以使用资源了。这个方法的使用要求很多,总之需要当前线程获得被调用的notify方法的对象的monitor

notifyAll

除了通知所有的线程可以准备执行之外,跟上面的方法要求一样。但是只有一个线程会被选择然后执行,这个就跟优先级和其他状态有关系了。

interrupt

中断线程

不建议使用的方法

方法

说明

stop

强制使当前的线程停止执行。实际上,作为开发人员我们会意识到,线程的复杂程度是没有边际的,而这个方法这样武断的停止一个线程,必然导致问题产生。也就是说,这个方法天生就有问题。比如说一个线程掌握了很多对象,并且改变了其中一些的状态,如果突然当前对象突然被停止,将会释放这些对象的monitor,这个时候被改变状态的对象就是被损坏的对象,其他线程再来操作的时候问题就出来了。替代的办法就是让当前线程正常结束,不使用这个方法。就是我们设置一些标志,如果这些标志满足的时候,我们结束线程

suspend

这个方法天生就有导致死锁的可能。如果当前线程持有很多对象的锁,但是当他suspend的时候,这些锁是不会释放的,想想就知道应该什么可能会发生,所以这个方法应该尽量不用。这里我们有办法替代这个方法,其实根替代stop的方法差不多,就是用wait方法来实现挂起,而不是事实上的挂起。比如:

resume

很显然,这个方法和上面的方法是对应的,所以上面用了wait方法来替代,所以这边应该用notify这个方法或者notifyAll这个方法来替代。其实这边可以把上面的实现方式结合起来,实现一个可以安全stopsuspend线程。这个在我的源码里有实现,但是不知道是不是对的。不过感觉原则应该没有问题,那就是设置标志来结束或者挂起线程,而不是使用这些过时的方法。

 

关键字

说明

volatile

Volatile修饰的成员变量在每次被线程访问时,都强迫从共享内存中重读该成员变量的值。而且,当成员变量发生变化时,强迫线程将变化值回写到共享内存。这样在任何时刻,两个不同的线程总是看到某个成员变量的同一个值。

synchronized

 1)synchronized关键字可以作为函数的修饰符,也可作为函数内的语句,也就是平时说的同步方法和同步语句块。如果再细的分类,synchronized可作用于instance变量、object reference(对象引用)static函数和class literals(类名称字面常量)身上。

  2)无论synchronized关键字加在方法上还是对象上,它取得的锁都是对象,而不是把一段代码或函数当作锁,而且同步方法很可能还会被其他线程的对象访问。

  3)每个对象只有一个锁(lock)与之相关联。

  4)实现同步是要很大的系统开销作为代价的,甚至可能造成死锁,所以尽量避免无谓的同步控制。

 

 

线程的周期

线程也有它完整的生命周期,线程的整个周期由线程的创建、线程的启动、线程的阻塞和线程的停止等部分组成。

 

一个线程有4种状态,任何一个线程肯定处于这4种状态中的一种。

1初始态又成创建状态(New):一个线程调用了new方法产生了一个线程对象之后,并在调用start方法之前的所处状态。此时系统不为它分配资源。在初始态中,只能调用startstop方法,调用其他方法将抛出非法状态例外(IllegalThreadStateException)的异常。

 

2)可执行状态(Runnable):执行了一个线程对象的start()方法后,线程就转到Runnable 状态。每个支持多线程的系统都有一个排程器,排程器会从线程池中选择一个线程并启动它。当一个线程处于可执行状态时,表示它可能正处于线程池中等待排程器启动它;也可能它已正在执行。注意,如果线程处于Runnable状态,它也有可能不在执行中,这是因为还有优先级和调度问题。

 

3)阻塞状态(NonRunnable):线程处于NonRunnable状态,这是由两种可能性造成的:要么是因挂起而暂停的,要么是由于某些原因而阻塞的,例如包括等待IO请求的完成。如通过对一个线程调用wait()函数后,线程就进入阻塞状态,只有当两次对该线程调用notifynotifyAll后它才能两次回到可执行状态。当一个线程处于阻塞状态时,系统排程器就会忽略它,不对它进行排程。当处于阻塞状态的线程重新回到可执行状态时,它有可能重新执行。

 

4)退出(Done):当一个线程正常结束,它便处于退出状态。这有两种可能性,要么是线程的run()方法执行完毕,要么是调用了stop()方法。

 线程状态的转换

11-1                                                         线程状态转换函数

   

   

start()

开始执行一个线程

New

Runnable

stop()

结束执行一个线程

NewRunnable  

Done

sleep(long)  

暂停一段时间,这个时间为给定的毫秒  

Runnable

NonRunnable

sleep(long,int)

暂停片刻,可以精确到纳秒  

Runnable

NonRunnable

suspend()  

挂起执行  

Runnable

NonRunnable  

resume()

恢复执行  

NonRunnable

Runnable  

yield()  

明确放弃执行  

Runnable

Runnable

 

如何创建一个简单的线程

一种是继承Thread

一种为实现Runnable 接口

两者都要重写run()方法。

 

 

 

/*

 * 继承Thread的方式

 */

class testThread extends Thread {

    public void run(){

        //do somethings

    }

    public static void main( String args[] ){

        testThread t = new testThread( );

        t.start();

    }

}

/*

 * 实现Runnable 接口

 */

class testThread implements Runnable{

        public void run(){

        //do somethings 

    }

    public static void main( String args[] ){

                    Runnable testThread =new testThread ();

Thread myThread=new Thread(testThread);

           myThread.start();

    }

}

  

你可能感兴趣的:(java,多线程,thread,OS)