一个线程理解成以下三个部分的组合:
(1)CPU:虚拟的CPU,专门用于执行该线程的任务。
(2)Code:代码,即线程中要执行的指令,在程序中表现为特定的方法。
(3)Data:数据,即线程中要处理的数据,在程序中表现为变量。
在Java中,由java.lang.Thread 类来实现线程的概念,其中:
虚拟的CPU,由java.lang.Thread 类封装和虚拟;
CPU所执行的代码,在构造Thread类时,传递给Thread 类对象。
CPU所处理的数据,在构造Thread 类时,传递给Thread 类对象。
为了构造一个Thread 类,可以向Thread的构造函数传递一个Runnable对象,这个对象就是线程所需要的代码和数据的封装。Runnable对象是指实现了java.lang.Runnable接口的任何对象,Runnable接口只有一个
方法:public void run();这个run()方法实际上就是线程所要执行的代码。
要启动线程中的代码,只需要执行Thread 类的start()方法,则系统会在可能的情况下去执行run()方法中所规定的代码。
创建线程对象,要传递代码与数据,而传递代码与数据有两种方法,一是通过继承Thread 类,一是Thread 类传递一个Runnable对象。
1.通过继承Thread 类创建线程
从Thread派生出一个新类,在其中加入属性及方法,同时覆盖run()方法。当创建这样一个派生类的新对象后,使用start()方法,即可启动该线程。
public class TestThread1{ public static void main(String args[]){ Thread t = new MyThread(); t.start(); } } class MyThread extends Thread { public void run() { //code } }
2.通过向Thread()构造方法传递Runnable对象来创建线程
public class TestThread2{ public static void main(String args[]){ MyTask mytask = new MyTask(100); Thread thread = new Thread(mytask); thread.start(); } } class MyTask implements Runnable{ private int n; public MyTask(int n){ this.n = n; } public void run() { //code } }
该程序定义了一个类MyTask,它实现了Runnable 接口,也就是说,它含有public void run()方法,在创建线程时,先创建一个MyTask对象,再将此对象作为Thread构造方法的参数。
注:
(1)run()方法规定了线程要执行的任务,但一般不是直接调用run()方法,而是通过线程的start()来启动线程。
(2)有时程序会调用Thread 类的一个static 方法:sleep(),它表示线程等待(休眠)一定的时间(单位为毫秒),但休眠用的时间一般不会严格等于所给定的时间。休眠结束后,系统发出一个InterruptedException 异常,来告诉休眠的结束。
上面两种方法的比较
直接继承Thread 类,这种方法的特点是:编写简单,可以直接操纵线程;但缺点也是明显的,因为若继承Thread类,就不能再从其他类继承。
使用Runnable接口,这种方法的特点是:可以将Thread 类与所要处理的任务的类分开,形成清晰的模型;还可以从其他类继承。
另外,若直接继承Thread类,在类中this即指当前线程;若使用Runnalbe接口,要在类中获得当前线程,必须使用Thread.currentThread()方法。
线程的优先级设置
同时处于就绪状态的线程,优先级高的,有优先被调度的权利。相同优先级,一般遵循先到先服务的原则。但是,这种情况不一定十分严格,因为实际的执行过程,与Java虚拟机的实现情况有关。
Thread类有三个有关线程优先级的静态常量:MIN_PRIORITY,MAX_PRIORITY,NORM_PRIORITY。其中,MIN_PRIORITY代表最小优先级,通常为1;MAX_PRIORITY代表最高优先级,通常为10;NORM_
PRIORITY代表普通优先级,默认数值为5。
对应一个新建线程,系统会遵循如下的原则为其指定优先级。
(1) 新建线程将继承创建它的父线程的优先级。父线程是指执行创建新线程对象语句的线程,它可能是程序的主线程,也可能是某一个用户自定义的线程。
(2) 一般情况下,主线程具有普通优先级。
另外,用户可以通过调用Thread 类的方法setPriority(int priority)来修改系统自动设定的线程优先级,使之符合程序的特定需要。
public class TestThreadPriority{ public static void main(String args[]){ Thread t1 = new Thread(new Runner(1)); Thread t2 = new Thread(new Runner(2)); Thread t3 = new Thread(new Runner(3)); t1.setPriority(Thread.MIN_PRIORITY); t2.setPriority(Thread.NORM_PRIORITY); t3.setPriority(Thread.MAX_PRIORITY); t1.start(); t2.start(); t3.start(); } } class Runner implements Runnable{ int id; Runner(int id){ this.id = id; } public void run(){ //code } }
执行的顺序为:t3-->t2-->t1。
线程的基本控制
1.结束线程
在JDK1.0中,可以用Thread对象的stop()方法来停止线程。但在以后的JDK版本中,stop()已经不主张用了。现在一般采取给线程设定一个标记变量的方法来决定线程是否应该终止。
2.设定线程的优先级
前面提过,设定线程的优先级可以使用Thread对象的setPriority(int priority)方法。
3.暂时阻止线程的执行
在JDK1.0中,可以用Thread对象的suspend()方法来暂时阻止线程的执行,用resume()方法来恢复线程的执行,不过这两个方法已经不主张用了。目前常用的方法如下:
(1)sleep()方法。用Thread.sleep(long millisecond)来挂起线程的执行。sleep()方法可以给优先级较低的线程以执行的机会。其基本使用方法是:
try{ Thread.sleep( 1000 ); }catch( InterruptedException e ){ //code }
(2)join()方法。调用某Thread对象的join()方法,可以将一个线程加入到本线程中,本线程的执行会等待另一线程执行完毕。join()方法可以不带参数,也可以带上一个long,表示等待的最长时间。其基本使用方法是:
Thread t; // t是另一线程 try{ t.join(); }catch( InterruptedException e ){ //code }
(3)yield()方法。Thread对象的yield()方法,可以给其他线程以执行的机会。如果没有其他可运行的线程,则该方法不产生任何作用。
线程的同步与共享
前面所提到的线程都是独立的,而且异步执行,也就是说每个线程都包含了运行时所需要的数据或方法,而不需要外部的资源或方法,也不必关心其他线程的状态或行为。但是经常有一些同时运行的线程需要共享数据,例如一个线程向文件写数据,而同时另一个线程从同一文件中读取数据,因此就必须考虑其他线程的状态与行为,这时就需要实现同步来得到预期结果。
若变量为成员变量,则多线程对同一成员变量进行操作时,他们对该成员变量是彼此影响的,即一个线程对成员变量的改变会影响另一个线程。
若变量为局部变量,则每个线程都会有一个局部变量拷贝,一个线程对该局部变量的改变不会影响另一个线程。
这种由于多线程同时操作一个对象引起的现象,称为该对象不是线程安全的。为了多线程机制能够正常运转,需要采取一些措施来防止两个线程访问相同的资源的冲突,特别是在关键的时期。为防止出现这样的冲突,只需在线程使用一个资源时为其加锁即可。访问资源的第一个线程加上锁以后,其他线程便不能再使用那个资源,除非第一个线程被解锁。Java中使用synchronized关键字来实现线程安全。在任何时刻,只能有一个线程调用特定对象的一个synchronized方法(尽管那个线程可以调用多个对象的同步方法)。
调用任何synchronized方法时,对象就会被锁定,不可再调用那个对象的其他任何synchronized方法,除非第一个方法完成了自己的工作,并解除锁定。因此,一个特定对象的所有synchronized方法都共享着一把锁,而且这把锁能防止多个方法对通用内存同时进行写操作(比如同时有多个线程)。
每个类也有自己的一把锁(作为类的Class对象的一部分),所以synchronized static方法可在一个类的范围内被相互间锁定起来,防止与static数据的接触。当线程访问某个synchronized static方法时,它锁的不是synchronized方法所在的对象,而是synchronized方法所在对象所对应的Class对象。注意如果想保护其他某些资源不被多个线程同时访问,可以强制通过synchronized方法访问那些资源。
由于通常将数据元素设为从属于private(私有),然后只通过方法访问那些内存,所以只需将一个特定的方法设为synchronized(同步的),便可有效地防止冲突。
但对于非private域,则不能保证这一点(因为它可能直接访问,而不通过synchronized方法)。
synchronized关键字除了可用在方法名前面外,还可以用在一个方法的内部,其格式如下:
synchronized(对象){ //语句块 }
表示在这语句执行期间,给某对象上锁。这里,对象可以用this。
相关推荐
4. **线程状态**:Java线程有五种状态:新建、可运行、运行、阻塞和死亡。了解这些状态可以帮助开发者更好地控制和调试线程。 5. **线程优先级**:每个线程都有一个优先级,Java中从1(`MIN_PRIORITY`)到10(`MAX_...
Java线程有10个优先级(MIN_PRIORITY, NORM_PRIORITY, MAX_PRIORITY),默认优先级是NORM_PRIORITY。但是,线程优先级并不保证绝对的执行顺序,操作系统调度策略可能影响实际执行顺序。 7. join()方法: 一个线程...
学习这个项目,我们可以深入理解Java线程的创建、同步和协作,以及如何通过`wait()`和`notify()`实现线程间的通信。此外,通过分析和调试这些类,我们还可以掌握多线程环境中的死锁、活锁和饥饿等问题的识别和解决...
在Java编程语言中,线程扮演着至关重要的角色,特别是在多任务处理和并发执行中。线程使得程序能够同时执行多个任务,提高了系统的效率和响应性。以下是对Java中线程作用的详细解释: 首先,线程是程序执行的最小...
Java中线程思维导图
在Java编程语言中,线程是程序执行的最小单元,它可以与程序的其他部分并行运行。理解如何创建和管理线程是Java开发者必备的技能。本文将详细讲解Java中线程的三种基本创建形式,并通过实例进行深入解析。 ### 1. ...
java中线程的相关知识及语法总结
在Java编程中,线程执行死循环可能会导致一系列的后果,尤其是在多线程环境中。首先,我们要理解死循环的概念:一个死循环就是程序中的某个循环条件始终为真,导致循环无法自然终止,持续消耗CPU资源。 标题所提及...
- Java中线程调度采用的是抢占式调度模式,即高优先级的线程会抢占低优先级线程的执行权。 3. **线程状态**: - 新建(New):线程对象刚刚被创建时的状态。 - 就绪(Runnable):线程对象创建后,其他线程调用...
Java多线程是Java编程语言中一个非常重要的概念,它允许开发者在一个程序中创建多个执行线程并行运行,以提高程序的执行效率和响应速度。在Java中,线程的生命周期包含五个基本状态,分别是新建状态(New)、就绪...
本案例将深入探讨Java多线程中的关键知识点,包括线程同步、线程通信和线程阻塞。 线程同步是为了防止多个线程同时访问共享资源,导致数据不一致。Java提供了多种同步机制,如synchronized关键字、Lock接口...
Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式...
### JAVA中的单线程与多线程概念解析 #### 单线程的理解 在Java编程环境中,单线程指的是程序执行过程中只有一个线程在运行。这意味着任何时刻只能执行一个任务,上一个任务完成后才会进行下一个任务。单线程模型...
在A线程中,我们可以创建一个CountDownLatch,初始化为2(表示B和C两个线程),然后在B和C线程的最后调用countDown()。A线程通过await()方法阻塞自己,直到计数值变为0。 ```java CountDownLatch latch = new ...
在本实验报告中,我们探讨了Java多线程技术在实际编程中的应用,特别是通过编写applet程序展示了如何实现滚动字符串和动态动画效果。实验主要分为两个部分:滚动字符串和蓝色反弹球。以下是对这些知识点的详细说明:...
由于数据库连接是一种昂贵的资源,应避免在每个线程中重复创建连接,通常采用连接池的方式进行管理。 3. **数据插入操作**:代码示例展示了如何使用预编译语句(PreparedStatement)执行数据插入操作。预编译语句...
Java 模拟线程并发是编程领域中的一个重要概念,尤其在多核处理器和高并发应用中,理解并熟练掌握线程并发技术对于提升程序性能至关重要。在Java中,线程并发可以通过多种方式实现,包括继承Thread类、实现Runnable...
Java多线程是Java编程中的重要概念,尤其在如今的多核处理器环境下,理解并熟练掌握多线程技术对于提高程序性能和响应速度至关重要。本资料详细讲解了Java多线程的原理,并提供了丰富的实战代码,非常适合Java初学者...
Java多线程机制是Java编程中至关重要的一部分,它允许程序同时执行多个任务,提升应用程序的效率和响应性。以下是对各个知识点的详细说明: 9.1 Java中的线程: Java程序中的线程是在操作系统级别的线程基础上进行...