java中的线程问题

                 今天简单介绍一下单线程的相关内容。

                  线程是java中的重要内容,有时也被称为轻量级进程,是程序执行流的最小单元 。线程是程序中一个单一的顺序控制流程,在单个程序中同时运行多个线程完成不同的工作,称为多线程。

                  计算机程序得以执行的3个要素是:CPU,程序代码和可存取的数据。在java语言中,多线程的机制是通过虚拟CPU来实现的,可以形象的理解为,在一个java语言内部虚拟了多台计算机,每台计算机对应一个线程,有自己的CPU,可以获取所需的代码和数据,因此能独立执行任务,相互之间还可以共用代码和数据。

                   java的线程是通过java.lang.Thread类来实现的,它内部实现了虚拟CPU的功能,能够接收和处理传递给它的代码和数据,并提供了独立的运行控制功能。

                  下面看一下Thread类的源码:

                     再看看Runable接口的源码:

                     可见Thread类实现了Runnable接口,同时在Thread类中,有一些比较关键的属性,比如name是表示Thread的名字,可以通过Thread类的构造器中的参数来指定线程名字,priority表示线程的优先级(最大值为10,最小值为1,默认值为5),daemon表示线程是否是守护线程,target表示要执行的任务。我们在创建线程的时候,一种方式就是通过Thread来实现,第二种是通过实现Runable接口并实现接口中定义的唯一的方法run()。这两种方法各有各的好处和缺点:直接继承Thread类:不能再从其他类继承;编写简单,可以直接操纵线程;使用Runable接口:可以将CPU,代码和数据分开,形成清晰的模型,还可以再从其他类继承,保持了程序风格的一致性。

                     Thread类中还有一些方法,我复制了CSDN中seapeak007的博客内容,觉得总结的不错。

                      方法摘要 
static int activeCount() 
          返回当前线程的线程组中活动线程的数目。 
 void checkAccess() 
          判定当前运行的线程是否有权修改该线程。 
 int countStackFrames() 
          已过时。 该调用的定义依赖于 suspend(),但它遭到了反对。此外,该调用的结果从来都不是意义明确的。 
static Thread currentThread() 
          返回对当前正在执行的线程对象的引用。 
 void destroy() 
          已过时。 该方法最初用于破坏该线程,但不作任何清除。它所保持的任何监视器都会保持锁定状态。不过,该方法决不会被实现。即使要实现,它也极有可能以 suspend() 方式被死锁。如果目标线程被破坏时保持一个保护关键系统资源的锁,则任何线程在任何时候都无法再次访问该资源。如果另一个线程曾试图锁定该资源,则会出现死锁。这类死锁通常会证明它们自己是“冻结”的进程。有关更多信息,请参阅为何不赞成使用 Thread.stop、Thread.suspend 和 Thread.resume?。 
static void dumpStack() 
          将当前线程的堆栈跟踪打印至标准错误流。 
static int enumerate(Thread[] tarray) 
          将当前线程的线程组及其子组中的每一个活动线程复制到指定的数组中。 
static Map<Thread,StackTraceElement[]> getAllStackTraces() 
          返回所有活动线程的堆栈跟踪的一个映射。 
 ClassLoader getContextClassLoader() 
          返回该线程的上下文 ClassLoader。 
static Thread.UncaughtExceptionHandler getDefaultUncaughtExceptionHandler() 
          返回线程由于未捕获到异常而突然终止时调用的默认处理程序。 
 long getId() 
          返回该线程的标识符。 
 String getName() 
          返回该线程的名称。 
 int getPriority() 
          返回线程的优先级。 
 StackTraceElement[] getStackTrace() 
          返回一个表示该线程堆栈转储的堆栈跟踪元素数组。 
 Thread.State getState() 
          返回该线程的状态。 
 ThreadGroup getThreadGroup() 
          返回该线程所属的线程组。 
 Thread.UncaughtExceptionHandler getUncaughtExceptionHandler() 
          返回该线程由于未捕获到异常而突然终止时调用的处理程序。 
static boolean holdsLock(Object obj) 
          当且仅当当前线程在指定的对象上保持监视器锁时,才返回 true。 
 void interrupt() 
          中断线程。 
static boolean interrupted() 
          测试当前线程是否已经中断。 
 boolean isAlive() 
          测试线程是否处于活动状态。 
 boolean isDaemon() 
          测试该线程是否为守护线程。 
 boolean isInterrupted() 
          测试线程是否已经中断。 
 void join() 
          等待该线程终止。 
 void join(long millis) 
          等待该线程终止的时间最长为 millis 毫秒。 
 void join(long millis, int nanos) 
          等待该线程终止的时间最长为 millis 毫秒 + nanos 纳秒。 
 void resume() 
          已过时。 该方法只与 suspend() 一起使用,但 suspend() 已经遭到反对,因为它具有死锁倾向。有关更多信息,请参阅为何不赞成使用 Thread.stop、Thread.suspend 和 Thread.resume?。 
 void run() 
          如果该线程是使用独立的 Runnable 运行对象构造的,则调用该 Runnable 对象的 run 方法;否则,该方法不执行任何操作并返回。 
 void setContextClassLoader(ClassLoader cl) 
          设置该线程的上下文 ClassLoader。 
 void setDaemon(boolean on) 
          将该线程标记为守护线程或用户线程。 
static void setDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh) 
          设置当线程由于未捕获到异常而突然终止,并且没有为该线程定义其他处理程序时所调用的默认处理程序。 
 void setName(String name) 
          改变线程名称,使之与参数 name 相同。 
 void setPriority(int newPriority) 
          更改线程的优先级。 
 void setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh) 
          设置该线程由于未捕获到异常而突然终止时调用的处理程序。 
static void sleep(long millis) 
          在指定的毫秒数内让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度程序精度和准确性的影响。 
static void sleep(long millis, int nanos) 
          在指定的毫秒数加指定的纳秒数内让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度程序精度和准确性的影响。 
 void start() 
          使该线程开始执行;Java 虚拟机调用该线程的 run 方法。 
 void stop() 
          已过时。 该方法具有固有的不安全性。用 Thread.stop 来终止线程将释放它已经锁定的所有监视器(作为沿堆栈向上传播的未检查 ThreadDeath 异常的一个自然后果)。如果以前受这些监视器保护的任何对象都处于一种不一致的状态,则损坏的对象将对其他线程可见,这有可能导致任意的行为。stop 的许多使用都应由只修改某些变量以指示目标线程应该停止运行的代码来取代。目标线程应定期检查该变量,并且如果该变量指示它要停止运行,则从其运行方法依次返回。如果目标线程等待很长时间(例如基于一个条件变量),则应使用 interrupt 方法来中断该等待。有关更多信息,请参阅为何不赞成使用 Thread.stop、Thread.suspend 和 Thread.resume?。 
 void stop(Throwable obj) 
          已过时。 该方法具有固有的不安全性。有关详细信息,请参阅 stop()。该方法的附加危险是它可用于生成目标线程未准备处理的异常(包括若没有该方法该线程不太可能抛出的已检查的异常)。有关更多信息,请参阅为何不赞成使用 Thread.stop、Thread.suspend 和 Thread.resume?。 
 void suspend() 
          已过时。 该方法已经遭到反对,因为它具有固有的死锁倾向。如果目标线程挂起时在保护关键系统资源的监视器上保持有锁,则在目标线程重新开始以前任何线程都不能访问该资源。如果重新开始目标线程的线程想在调用 resume 之前锁定该监视器,则会发生死锁。这类死锁通常会证明自己是“冻结”的进程。有关更多信息,请参阅为何不赞成使用 Thread.stop、Thread.suspend 和 Thread.resume?。 
 String toString() 
          返回该线程的字符串表示形式,包括线程名称、优先级和线程组。 
static void yield() 
          暂停当前正在执行的线程对象,并执行其他线程。 

                      接下来说说线程的基本状态。线程的状态分为4种:创建(New),可运行(Runable),阻塞(Blocked)和死亡(Dead)。

                      下面说说执行情况。当使用new来创建一个线程时,它处于创建状态,这个时候,线程并未进行任何操作,然后调用线程的start()方法,来向线程调度程序(通常是JVM(java虚拟机)或操作系统)注册一个线程,这个时候,这个线程一切就绪,就等待CPU时间了。线程调度程序根据调度策略来调度不同的线程,调用线程的run()方法给已经注册的各个线程以执行的机会,被调度的程序进入运行(Running)状态。当线程的run()方法运行完毕,线程将被抛弃,进入死亡(Dead)状态。不能调用restart()方法来重新开始一个处于死亡状态的线程,但是可以调用处于死亡状态的线程对象的各个方法。如果线程在运行(Running)状态中因为I/O阻塞,等待键盘输入,调用了线程的sleeo()方法,调用了对象的wait()方法等,则线程将进入阻塞(Blocked)状态,直到这些阻塞原因被解除。线程调度程序会根据调度情况,将正在运行(Running)中的线程设置为Runable状态。

                     线程的结束方式有以下几种:1.让线程的Run()方法执行完,线程自然结束(此方法最好);2.通过轮询和共享标志位的方法来结束线程;3.线程抛出一个未捕获(Catch)到的Exception或Erro,通过调用interrupt方法和捕获InterruptedException异常来终止线程;4.使用线程池,当线程不用了,就让它sleep并放进队列中。

 

原文地址:https://www.cnblogs.com/Wangjiaq/p/8640952.html