Java多线程并发实战
JVM的抽象理解(1/2)
JVM
Memory
通过阅读“静态的代码”,对一个软件中线程的梳理和理解,能够彻底理清一个 复杂的软件系统的工作流程,并且能够“动态”的理解软件系统,包括一些开源 软件。
JVM的抽象理解(2/2)
SOAP/Rest
http/https RMI
JMS JNDI
JVM
ICMP/SNMP
通过Runnable接口创建
步骤1:创建实现Runnable接口的类: class SomeRunnable implements Runnable public void run() { //do something here } } {
步骤2:创建一个类对象: Runnable oneRunnable = new SomeRunnable(); 步骤3:由Runnable创建一个Thread对象: Thread oneThread = new Thread(oneRunnable); 步骤4:启动线程: oneThread.start();
加载的类太多有可能撑爆PermGen Space: Exception in thread "main" ng.OutOfMemoryError: PermGen space 这个异常很方便通过JVM启动参数来模拟演示
JVM相关参数设置(Stack)
Java Stack 栈是存放线程调用方法时存储局部变量表,操作,方法出口等 与方法执行相关的信息,栈大小由Xss来调节,例如: set java_opt=-Xss128k:设置每个线程的堆栈大小。
获取锁
释放锁
多线程并发执行
ReadWriteLock编程示例
public class ReadWriteLockTest { private double price = 0; private ReadWriteLock lock = new ReentrantReadWriteLock(); public double getPrice() { lock.readLock().lock(); double value = price; lock.readLock().unlock(); return value; } public void setPrice(double price) { lock.writeLock().lock(); this.price = price; lock.writeLock().unlock(); } }
一个线程可以创 建和撤销另一个 线程;同一个进 程中的多个线程 之间可以并发执 行,相对进程而 言,线程是一个 更加接近于执行 体的概念,它可 以与同进程中的 其他线程共享数 据,但拥有自己 的栈空间,拥有 独立的执行序列。
线程的状态
创建线程的几种方法
编写多线程程序是为了实现多任务的并发执行,从而能够更好地与用户交 互。 一般有三种方法: Thread, Runnable, Callable. Runnable和Callable的区别是, (1)Callable规定的方法是call(),Runnable规定的方法是run(). (2)Callable的任务执行后可返回值,而Runnable的任务是不能返回值 得 (3)call方法可以抛出异常,run方法不可以 (4)运行Callable任务可以拿到一个Future对象,表示异步计算的结果。 它提供了检查计算是否完成的方法,以等待计算的完成,并检索计算的结 果。通过Future对象可以了解任务执行情况,可取消任务的执行,还可获 取执行结果。
Java 内存空间的理解
线程1 线程2 线程n
Method Area
Heap
Stack
Memory
JVM
Native Stack
JVM相关参数设置(Heap)
Java Heap
所有对象的实例分配都在Java堆上分配内存 堆大小由-Xmx和-Xms来调节 例如:set java_opt=-Xms512m -Xmx1024m
JVM
HEAP
目录
1 2 3 4 5 引言
Java多线程基础
Java并发编程中锁的运用 Java多线程高级编程(一)
Java多线程高级编程(二)
锁的高级运用
Lock
ReadWriteLock
ReentrantLock
ReentrantReadWriteLock
相比synchronized关键字, Lock接口提供了更为灵活的代码块控制 支持tryLock()方法,没有获取锁时,可继续执行而不阻塞 支持读写分离操作,允许多个线程读和一个写线程操作 相比synchronized,Lock接口机制具有更好的性能
Lock编程示例
public class ReentrantLockTest { private final Lock queueLock = new ReentrantLock(); private void doWork() { queueLock.lock(); try { String name = Thread.currentThread().getName(); Long duration = (long) (Math.random() * 10000); System.out.println(name + " sleep " + duration / 1000 + " seconds"); Thread.sleep(duration); } catch (InterruptedException e) { e.printStackTrace(); } finally { queueLock.unlock(); } } public static class MyJob implements Runnable { private ReentrantLockTest test = null; public MyJob(ReentrantLockTest test) { this.test = test; } public void run() { Test.doWork(); } } public static void main(String[] args) { ReentrantLockTest test = new ReentrantLockTest(); MyJob job = new MyJob(test); for (int i = 0; i < 10; i++) { Thread thr = new Thread(job); thr.setName("job-" + i); thr.start(); } } }
通过继承Thread类创建
public class ThreadTest { public void test() { Thread myThread = new MyThread(); myThread.start(); } class MyThread extends Thread { public void run() { // TODO } } }
锁对象为 TestObject.class 锁对象为 this 锁对象为 TestObject.class 锁对象为 TestObject.class
锁对象为 this
锁对象为 lock
锁对象为 lock
锁的理解
线程1
线程2
线程3
Method Area
TestObject.class TestObject this Object lock
Memory
JDBC
锁的产生及运用
JVM中多线程的 并发执行 锁的运用
共享资源的访问
多线程的线程同步机制实际上是靠锁的概念来控制 线程对资源访问操作前必须获取资源的锁
共享资源的产生
线程1 线程2 线程n
Method Area
Heap
Stack
Memory
JVM
Native Stack
Synchronized关键字运用
public class TestObject { private Object lock = new Object(); public static synchronized void mA () { // do something; } public synchronized void mB () { // do something; } public void mC () { synchronized (TestObject .class) { // do something; } } public void mD () { synchronized (this.getClass ()) { // do something; } } public void mE () { synchronized (this) { // do something; } } public void mF () { synchronized (lock) { // do something; ock.wait(); } } public void mG () { synchronized (lock) { // do something; lock.notifyAll(); } } }
OS(windows/Linux)
硬件(CPU+Memory+Storage)
进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动, 进程是系统进行资源分配和调度的一个独立单位. 线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小 的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一 点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可 与同属一个进程的其他的线程共享进程所拥有的全部资源.