关于java中的线程主要介绍一下以下几个方面:1、线程的创建和启动 2、线程的生命周期 3、线程同步(重点)
---------------------------------------------------------------------------------
1、线程的创建和启动:
i)线程的创建:线程的创建有两种方式:继承java.lang.Thread类;实现java.lang.Runable接口。
对于继承java.lang.Thread类的线程,在创建了这个线程以后,我们要重写该类的run()方法,而run方法的方法体是当前该线程要做的事情。
对于实现java.lang.Runable接口的线程,在创建了该线程之后,也要实现run()方法。(注意:其中java.lang.Thread这个类也是实现了java.lang.Runable接口的)。eg:
public class MyThread1 extends Thread{ @Override public void run() { for (int i = 0; i < 100; i++) { System.out.println(getName() + ":" + i); } } } public class MyThread2 implements Runnable{ @Override public void run() { for (int i = 0; i < 100; i++) { System.out.println(Thread.currentThread().getName() + ":" + i); } } }
以上两个线程分别使用两种方式被创建。run方法都是循环100次输出当前线程的名字。在第二种方式中,由于java.lang.Thread这个类也是实现了java.lang.Runable接口,所以可以使用Thread类的方法currentThread()方法来获得当前线程。
ii)线程的启动:线程的启动要使用start()方法。我们首先创建一个main方法,在main方法中启动线程,eg
public class Test{ public static void main(String[] args){ MyThread1 m1 = new MyThread1(); m1.start(); Thread t2 = new Thread(new MyThread2()); t2.start(); } }
对于线程二的启动,因为实现的是Runable接口,所以不能直接调用start方法,在Thread类的构造方法中,有一个参数是Runable接口的方法,由于MyThread2实现了该接口,所以使用 Thread类的该构造方法,启动start方法。
建和启动线程,倒不是因为哪一种方式更好,而是考虑到java的单继承,当一个类已经继承了另外一个类时,就不能再去继承Thread类,只能去实现Runable接口。
2、线程的生命周期:
线程只能创建和死亡一次,但是线程的其他三种方式却是可以循环多次的。一个线程被创建后,就会进入就绪队列等待调度,当获得处理器资源后就会进入运行状态,当该线程的run方法全部运行完后,该线程就会死亡,或者就会进入阻塞状态,阻塞结束后重新进入就绪状态。或在运行过程中市区处理器资源,直接进入就绪状态等待,依次循环,直到线程死亡。
3、线程同步:
在多线程中,当多个线程同时对同一个对象的同一个实例变量操作时,就可能引起线程不同步问题。
在此以两个人同时用一个账户取钱为例,说明并解决线程不同步的问题。
public class Account { private int money = 2000; public void getMoney(String name,int money) { //...此处省略1000行 if(money < this.money) { this.money -= money; System.out.println(name + "取款成功"); } else { System.out.println(name + "余额不足"); } } }
public class Rose extends Thread{ private Account account; public Rose(Account account) { this.account = account; } @Override public void run() { try { Thread.sleep(300); account.getMoney("rose", 1500); } catch (InterruptedException e) { e.printStackTrace(); } } }
public class Tom extends Thread{ private Account account; public Tom(Account account) { this.account = account; } @Override public void run() { try { Thread.sleep(300); account.getMoney("tom", 1500); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
public class Test{ public static void main(String[] args){ Account account = new Account(); Tom tom = new Tom(account); Rose rose = new Rose(account); tom.start(); rose.start(); } }
运行结果截图:
之所以出现不同的结果,是因为对于两个不同的线程Rose和Tom调用account的takeMoney()方法时出现的线程的切换,当第一个线程完成if条件判断时,处理器资源突然给了另一个线程。这就造成了线程不同步,即现成不安全。
解决方案1:在方法声明上添加关键字synchronized,即对于Account类中的方法takeMoney()这样声明:public synchronized void takeMoney(),这样一旦一个线程run方法运行到这个方法时,就会上锁,阻止其他线程进入。从而实现线程同步。
解决方案2:使用synchronized同步代码块。我们只对可能引起线程不同步的那一部分代码上锁,而不是对整个方法上锁,从而提高程序的运行效率。即:将if选择包括在同步代码块中。
public class Account { private int money = 2000; public void getMoney(String name,int money) { //...此处省略1000行 synchronized(this){ if(money < this.money) { this.money -= money; System.out.println(name + "取款成功"); } else { System.out.println(name + "余额不足"); } } <span></span> } }
解决方案3:同步锁,引入java.util.concurrent.locks.ReentrantLock。在if选择运行前加锁,运行完这些代码后,在解锁。代码如下:
public class Account { private int money = 2000; private ReentrantLock reentrantLock = new ReentrantLock(); public void getMoney(String name,int money) { //...此处省略1000行 try{ reentrantLock.lock(); if(money < this.money) { this.money -= money; System.out.println(name + "取款成功"); } else { System.out.println(name + "余额不足"); } } finally { reentrantLock.unlock(); } } }
到此为止,javaSE就算告一段落了。期待后续补充、、、
相关推荐
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程序中的线程是在操作系统级别的线程基础上进行...
### Java线程基础 #### 一、操作系统中的线程与进程概念 在现代操作系统中,多线程是一种常见的实现多任务的方式。对于操作系统而言: - **进程**:指的是内存中运行的一个应用程序。每个进程拥有自己独立的一块...