Java基础之线程原子量

所谓的原子量即操作变量的操作是“原子的”,该操作不可再分,因此是线程安全的。为何要使用原子变量呢,原因是多个线程对单个变量操作也会引起一些问题。在Java5之前,可以通过volatile、synchronized关键字来解决并发访问的安全问题,但这样太麻烦。Java5之后,专门提供了用来进行单变量多线程并发安全访问的工具包java.util.concurrent.atomic,其中的类也很简单

package unit_fifteen;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicLong;

/**
* Java线程:新特征-原子量
*
*/
public class Test {
        public static void main(String[] args) {
                ExecutorService pool = Executors.newFixedThreadPool(2);
                Runnable t1 = new MyRunnable("张三", 2000);
                Runnable t2 = new MyRunnable("李四", 3600);
                Runnable t3 = new MyRunnable("王五", 2700);
                Runnable t4 = new MyRunnable("老张", 600);
                Runnable t5 = new MyRunnable("老牛", 1300);
                Runnable t6 = new MyRunnable("胖子", 800);
                //执行各个线程
                pool.execute(t1);
                pool.execute(t2);
                pool.execute(t3);
                pool.execute(t4);
                pool.execute(t5);
                pool.execute(t6);
                //关闭线程池
                pool.shutdown();
        }
} 

class MyRunnable implements Runnable {
        private static AtomicLong aLong =new AtomicLong(10000);        //原子量,每个线程都可以自由操作
        private String name;                //操作人
        private int x;                            //操作数额

        MyRunnable(String name, int x) {
                this.name = name;
                this.x = x;
        } 

        public void run() {
                System.out.println(name + "执行了" + x +",当前余额:" + aLong.addAndGet(x));
        }
}

上面是个反例,代码的结果是多变的

注意:原子量虽然可以保证单个变量在某一个操作过程的安全,但无法保证你整个代码块,或者整个程序的安全性。因此,通常还应该使用锁等同步机制来控制整个程序的安全性

package unit_fifteen;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.atomic.AtomicLong;

/**
* Java线程:新特征-原子量
*
*/
public class Test {
        public static void main(String[] args) {
                ExecutorService pool = Executors.newFixedThreadPool(2);
                Lock lock = new ReentrantLock(false);
                Runnable t1 = new MyRunnable("张三", 2000,lock);
                Runnable t2 = new MyRunnable("李四", 3600,lock);
                Runnable t3 = new MyRunnable("王五", 2700,lock);
                Runnable t4 = new MyRunnable("老张", 600,lock);
                Runnable t5 = new MyRunnable("老牛", 1300,lock);
                Runnable t6 = new MyRunnable("胖子", 800,lock);
                //执行各个线程
                pool.execute(t1);
                pool.execute(t2);
                pool.execute(t3);
                pool.execute(t4);
                pool.execute(t5);
                pool.execute(t6);
                //关闭线程池
                pool.shutdown();
        }
} 

class MyRunnable implements Runnable {
        private static AtomicLong aLong =new AtomicLong(10000);        //原子量,每个线程都可以自由操作
        private String name;                //操作人
        private int x;                            //操作数额
        private Lock lock;

        MyRunnable(String name, int x,Lock lock) {
                this.name = name;
                this.x = x;
                this.lock = lock;
        } 

        public void run() {
                lock.lock();
                System.out.println(name + "执行了" + x +",当前余额:" + aLong.addAndGet(x));
                lock.unlock();
        }
}
时间: 2024-08-28 18:19:52

Java基础之线程原子量的相关文章

(CZ深入浅出Java基础)线程笔记

一.线程的引入 1.多线程概述 1.1.进程 a.正在运行的程序,是系统进行资源分类和调用的独立单位. b.每个进程都有它自己的内存空间和系统资源. 1.2.线程 a.是进程中的单个顺序控制流,是一条执行路径. b.一个进程如果只有一条路径,则称为单线程程序. c.一个进程如果有多条执行路径,则称为多线程程序. 1.3.小结 线程多的进程抢到CPU执行权的概率大,但是仍具有随机性. 2.Java程序运行原理 2.1.Java运行 Java命令会启动Java虚拟机,启动JVM,等于启动了一个应用程

黑马程序员--Java基础--多线程|线程同步

--Java培训.Android培训.iOS培训..Net培训 期待与您共同交流!-- 多线程基础.线程同步 1. 多线程基础 1.1. 进程和线程 1.1.1. 什么是进程 所谓进程(process)就是一块包含了某些资源的内存区域.操作系统利用进程把它的工作划分为一些功能单元.进程中所包含的一个或多个执行单元称为线程(thread).进程还拥有一个私有的虚拟地址空间,该空间仅能被它所包含的线程访问.线程只能归属于一个进程并且它只能访问该进程所拥有的资源.当操作系统创建一个进程后,该进程会自动

Java基础之线程

进程与线程 进程:进程是指内存中运行得一个程序,每个进程都有一个独立的内存空间,一个应用程序可以同时运行多个进程:进程是程序运行的一次过程,是系统运行程序的基本单位. 线程:进程内部以个单独的独立执行单元,一个进程可以包含多个线程. 进程与线程的区别: 进程:有独立的存储空间,进程中的数据存放空间(栈空间和堆空间)是独立的,至少有一个线程 线程:堆空间是共享的,栈空间是独立的,线程消耗的资源比进程小得多 线程掉度 计算机CPU在任意时刻只能执行一条指令,每一个进程只有获得CPU的使用权才能去执行

【java基础】线程池

为什么要使用线程池 线程池用于多线程处理中,它可以根据系统的情况,可以有效控制线程执行的数量,优化运行效果.线程池做的工作主要是控制运行的线程的数量,处理过程中将任务放入队列,然后在线程创建后启动这些任务,如果线程数量超过了最大数量,那么超出数量的线程排队等候,等其它线程执行完毕,再从队列中取出任务来执行. 线程池的特点 线程复用 控制最大并发数量 管理线程 线程池的优点 降低资源消耗,通过重复利用已创建的线程来降低线程创建和销毁造成的消耗. 提高相应速度,当任务到达时,任务可以不需要的等到线程

Java基础之线程的两种实现方式

进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程中可以启动多个线程!线程总是属于某个线程,进程中的线程共享进程的内存 注意:对Java来说,run()方法没有任何特别之处.像main()方法一样,它只是新线程知道调用的方法名称(和签名).因此,在Runnable上或者Thread上调用run方法是合法的.但并不启动新的线程,启动新的线程要调用start()方法 在Java中提供了两种方式实现线程:1.继承Thread类 package unit_fifteen; p

Java基础之线程synchronized关键字

synchronized 关键字,它包括两种用法:synchronized 方法和 synchronized 块 1. synchronized 方法:通过在方法声明中加入 synchronized关键字来声明 synchronized 方法.如:  public synchronized void accessVal(int newVal);  synchronized 方法控制对类成员变量的访问:每个类实例对应一把锁,每个 synchronized 方法都必须获得调用该方法的类实例的锁方能执

Java基础之线程阻塞栈

阻塞栈,与阻塞队列相似.不同点在于栈是“后入先出”的结构,每次操作的是栈顶,而队列是“先进先出”的结构,每次操作的是队列头:Java为阻塞栈定义了接口:java.util.concurrent.BlockingDeque,其实现类也比较多 package unit_fifteen; import java.util.concurrent.BlockingDeque; import java.util.concurrent.LinkedBlockingDeque; /** * Java线程:新特征

Java基础之线程新特性条件变量

条件变量都实现了java.util.concurrent.locks.Condition接口,条件变量的实例化是通过一个Lock对象上调用newCondition()方法来获取的,这样,条件就和一个锁对象绑定起来了.因此,Java中的条件变量只能和锁配合使用,来控制并发程序访问竞争资源的安全.条件变量的出现是为了更精细控制线程等待与唤醒,在Java5之前,线程的等待与唤醒依靠的是Object对象的wait()和notify()/notifyAll()方法,这样的处理不够精细 package un

Java基础之线程阻塞队列

阻塞队列是Java线程新特征中的内容,Java定义了阻塞队列的接口java.util.concurrent.BlockingQueue,阻塞队列的概念是,一个指定长度的队列,如果队列满了,添加新元素的操作会被阻塞等待,直到有空位为止.同样,当队列为空时候,请求队列元素的操作同样会阻塞等待,直到有可用元素为止 阻塞队列还有很多实现类,用来满足各种复杂的需求:BlockingQueue.ArrayBlockingQueue, DelayQueue, LinkedBlockingQueue, Prio