Consider the following example:
package thread;
public class ThreadVerify {
public static boolean stop = false;
public static void main(String args[]) throws InterruptedException {
Thread testThread = new Thread(){
@Override
public void run(){
int i = 1;
while(!stop){
//System.out.println("in thread: " + Thread.currentThread() + " i: " + i);
i++;
}
System.out.println("Thread stop i="+ i);
}
};
testThread.start();
Thread.sleep(1000);
stop = true;
System.out.println("now, in main thread stop is: " + stop);
testThread.join();
}
}
The working thread is started to do increment on i and after one second, the flag is set as true in main thread. It is expected that we could see print out in working thread: “Thread stop i=”. Unfortunately it is NOT the case. Through process explorer we can find the working thread is still running:
The only way we can terminate it is to click this button in Eclipse:
The reason is: every thread in Java has its own thread local stack in runtime. Every time a thread tries to access the content of a variable, it first locates the variable content in the main memory, then loads this content from main memory to its local stack. Once this load is done, this relationship between thread local stack and main memory is cut.
Later, when thread performs modifications on the variable, the change is directly done on thread local stack. And at a given time ( scheduled by JVM, developer has no control about this timeslot), the change will be refreshed from thread local stack to memory. Back to our example, already the main thread has changed the flag to true in one second later ( this is TOO late! ), unfortunately when the working thread reads the flag from its own local stack, the flag is still false ( it makes sense since when it is copied from main memory in main thread ), so the working threads could never end. See the following picture for detail.
Solution is: add keyword volatile to flag variable, to force the read access on it in working thread is done always from main memory, so that after the flag is changed to true in main thread, later the working thread can detect this latest change since it reads data from main memory now. After this keyword is added we can get expected output:
要获取更多Jerry的原创文章,请关注公众号"汪子熙":
相关推荐
单例模式(Singleton Pattern)作为一种最基本的创建型设计模式,其主要目的是控制一个类的实例化过程,确保在整个应用程序中仅存在一个实例,并且该实例能够被全局访问。这种模式在实际软件开发中有着极其广泛的应用...
Java SE,全称为Java Standard Edition,是Java编程语言的核心部分,主要用来开发桌面应用程序。它提供了丰富的类库,包括集合框架、I/O流、多线程、网络编程、数据库连接等,是Java开发者必备的基础知识。 Java SE...
- **反射机制**:说明反射的用途及其实现方式,探讨其性能影响及应用场合。 - **自定义注解**:讲解自定义注解的使用场景及其实现过程。 - **List与Map区别**:比较List和Map的使用场景,以及ArrayList与LinkedList...
- **JVM (Java Virtual Machine)**:负责执行Java字节码,提供了一个运行时环境,使得Java程序可以在不同的操作系统上运行。 - **JRE (Java Runtime Environment)**:包含了JVM和执行Java应用程序所需的核心类库。...
面试中,你可能需要结合实际场景应用这些模式,解释其优点和适用场合。 面试技巧同样重要。简历上应清晰地表述你的技能掌握程度,引导面试官关注你的强项。在面试过程中,适时引导话题至你熟悉的领域,但要注意不要...
1. **Hibernate**:一个流行的Java持久化框架,用于简化数据库操作,支持ORM(对象关系映射),了解其核心概念和基本使用流程。 2. **Spring框架**:包括Spring Core、Spring MVC、Spring Boot等,掌握依赖注入(DI...
- **Contain**: 包含,用于表示一个集合是否包含另一个元素。 - **Capacity**: 容量,集合或容器的最大存储数量。 - **Enumeration**: 枚举,用于表示一组固定的值。 - **Comparable**: 可比较的,用于表示可以相互...
适用于需要快速查找和更新元素的应用场合,如:缓存管理、配置项存储等。 #### 2.6 树(Tree) 树形结构可以表示成一组节点以及它们之间的层次关系,包括但不限于二叉树、红黑树等多种变体。树在数据库索引、文件系统...
总结:单例模式是软件设计中的一个重要模式,用于控制类的实例化过程,确保在整个应用程序中只有一个实例存在。常见的 Java 实现包括饿汉式、懒汉式、双重检查锁和静态内部类。每种实现方式都有其优缺点,需要根据...
- 访问修饰符:private、default、protected、public的区别及其应用场合。 - 抽象类与接口:了解抽象类和接口的特性,理解它们在设计模式中的作用。 - 泛型:理解泛型的使用,类型擦除的概念,以及通配符的运用。...
- 实际应用中可通过合理设计哈希算法降低冲突概率。 #### NIO最佳实践 - 使用`Netty`、`MINA`等成熟框架简化开发过程。 - 高效利用`Selector`进行多路复用,提高性能。 #### TreeMap的实现原理 - `TreeMap`基于...
- **防止阻塞**:当一个线程因IO操作阻塞时,其他线程仍能继续执行,确保程序的连续运行。 - **便于建模**:通过分解大任务为多个小任务,简化编程模型,提高代码的可读性和维护性。 2. **创建线程方式** - **...
Java是一种广泛使用的面向对象的编程语言,以其跨平台、高性能和丰富的类库而备受开发者青睐。在准备Java面试时,了解其核心概念和技术是至关重要的。以下是一些关键的Java知识点,涵盖了从基础到高级的各个方面: ...
在实际应用中,单例模式常见于以下场合: - **配置信息类**:如XML配置文件的解析,只创建一个解析器实例来读取和管理配置信息。 - **数据库连接池控制类**:管理数据库连接,通过单例确保所有请求都使用同一组连接...
Java并发编程中,CAS(Compare and Swap,比较并交换)是一种无锁算法,常用于实现原子操作,它在多线程环境下提供了数据的...在实际应用中,开发者需要根据具体需求和环境来决定何时使用CAS,何时采用传统的锁机制。
- **工厂模式**:简单工厂、工厂方法、抽象工厂的设计思想及其应用场合。 - **代理模式**:JDK动态代理、CGLIB动态代理的原理及实现步骤。 - **装饰者模式**:与适配器模式的区别,具体应用场景示例。 - **观察者...