Java = multithreading - concurrency and high thread-safe, volatile, atomic class

First, multithreading

Parallel and Concurrent

Parallel: two events at the same time, they are taking place
concurrently: two events, in a period of time with, are taking place (alternate execution)

Processes and threads

Process: The program is running in memory, we call the process
threads: a small function module to complete the process (using a process execution unit functions)

A thread is part of a process of
      each process has its own memory space (separate stack independent of the heap, etc.), and at least one thread
      each thread will process an application with a separate stack, heap shared processes 

CPU thread calls means to quickly switch between different process threads of different
    
classification thread scheduling:
    time-sharing scheduling: each thread has an average execution of the CPU
    preemptive call: randomly assigned to each thread execution of the CPU (specific the number and distribution related to thread priority)
    our Java program (Java process) in all of the threads using preemptive scheduling 

State of the thread

Thread object There are six states: NEW (New), RUNNABLE (running), BLOCKED (blocking), WAITING (waiting), TIMED_WAITING (waiting time), TERMINATED (termination); the following state transitions:

 

1.Thread class

a.Thread类是什么?
    Thread是Java定义好的,代表线程的类,只要创建该类的一个对象,其实就是创建了一个线程
   
b.Thread类的构造方法
    public Thread(); // 无参构造,线程会有默认的名字,Thread-0,Thread-1等...
	public Thread(String name); //带有线程名字的构造

	public Thread(Runnable r);//带有线程任务的构造
	public Thread(Runnable r,String name); //即带有线程名字,又带有线程任务的构造
    
c.Thread类的成员方法
    public String getName(); //获取线程的名字
	public void setName(String name);//修改线程的名字

	public void run();//代表线程要执行的任务,任务有关的代码需要写在次方法中
	public void start();//线程只创建并不会执行,必须调用start开启后才会执行任务

	public static void sleep(long millis); //让当前线程"休眠/暂停"多少毫秒
			这里的当前线程只指 Thread.sleep(1000)这句代码写哪个线程中,哪个线程就是当前线程
	public static Thread currentThread();//获取当前线程对象
			这里的当前线程是指 Thread.currentThread() 这句代码写哪个线程中,哪个线程就是当前线程


线程执行有优先级,优先级越高先执行机会越大(并不是一定先执行!!)。优先级用int的priority参数表示。
线程优先级最高为10,最低为1。默认为5 

2. Create a new thread way - inheritance

a.描述:
	将类声明为 Thread 的子类。该子类应重写 Thread 类的 run 方法。接下来可以分配并启动该子类的实例
b.分析创建的步骤:
	i.创建子类 继承 Thread
    ii.子类中重写run方法(在run中编写线程要执行的任务代码)
    iii.创建子类对象(实际上就是创建一个线程对象)
    iv. 调用线程对象的start方法(启动该线程)    
c.案例:
	//i.创建子类 继承 Thread
    public class MyThread extends Thread {
        //ii.子类中重写run方法(在run中编写线程要执行的任务代码)
        @Override
        public void run() {
            for (int i = 0; i < 50; i++) {
                System.out.println("子线程..."+i);
            }
        }
    }
	public class ThreadDemo02 {
    public static void main(String[] args) {
        // iii.创建子类对象(实际上就是创建一个线程对象)
        MyThread mt = new MyThread();
        //iv. 调用线程对象的start方法(启动该线程)
        mt.start();
        //主线程 不会等待子线程任务结束
        for (int i = 0; i < 50; i++) {
            System.out.println("主线程..."+i);
        }
    }
}

注意:
	a.我们可以给线程起名字,也可以使用默认的名字
    b.我们获取线程的名字时:
			建议使用通用方式: Thread.currentThread().getName();
			如果是子线程内部也可以直接调用getName()获取子线程的名字

Second way to create a new thread implementation _

a.描述
    声明实现 Runnable 接口的类。该类然后实现 run 方法。
    然后可以分配该类的实例,在创建 Thread 时作为一个参数来传递	并启动.
b.分析步骤:
	i.创建实现类 实现 Runnable接口(实际上接口中一个任务方法,run方法)
    ii.实现类重写run方法(run中编写具体的任务代码)
    iii.创建实现类对象(该实现类对象并不是线程对象,我们称为任务对象) 
    iv. 创建Thread对象,同时传入实现类对象
        public Thread(Runnable r);//带有线程任务的构造
	v. 启动该线程(调用线程对象的start方法)
c.代码实现
    //i.创建实现类 实现 Runnable接口(实际上接口中一个任务方法,run方法)
    public class MyRunnable implements Runnable {
        //ii.实现类重写run方法(run中编写具体的任务代码)
        @Override
        public void run() {
            //run中写任务代码
            for (int i = 0; i < 50; i++) {
                System.out.println("子线程..."+i);
            }
        }
    }
    
	public class TestThread {
        public static void main(String[] args) {
            //iii.创建实现类对象(该实现类对象并不是线程对象,我们称为任务对象)
            MyRunnable mr = new MyRunnable();
            //iv. 创建Thread对象,同时传入实现类对象
            Thread tt = new Thread(mr);
            //v. 启动该线程(调用线程对象的start方法)
            tt.start();

            //主线程不会等待子线程执行完毕
            for (int i = 0; i < 50; i++) {
                System.out.println("主线程..."+i);
            }
        }
    }

Compare the pros and cons of two ways

Two ways to create a thread way, a better way to achieve
    a. Implementation is better, because the implementation of threads and tasks are separated, by their own combination programmer
    b. Implementation of Java single inheritance to avoid the lack of
    c. Implementation of threads and tasks are decoupled, inheritance threads and tasks are coupled
    d for the thread pool, we need a Runnable implementation class, without the need for a subclass of thread.
to sum up: in development we recommend the use of implementation (not to say that inherited the wrong way)   

Anonymous inner classes simplified way to create threads

匿名内部类作用:
	可以快速创建一个类的子类对象或者一个接口的实现类对象
public class TestDemo {
    public static void main(String[] args) {
        //1.继承方式创建线程
        new Thread(){
            @Override
            public void run() {
                for (int i = 0; i < 50; i++) {
                    System.out.println(Thread.currentThread().getName()+"..."+i);
                }
            }
        }.start();
        //2.实现方式创建线程
        new Thread(new Runnable(){
            @Override
            public void run() {
                for (int i = 0; i < 50; i++) {
                    System.out.println(Thread.currentThread().getName()+"..."+i);
                }
            }
        }).start();
        //主线程不会等待子线程任务结束
        for (int i = 0; i < 50; i++) {
            System.out.println(Thread.currentThread().getName()+"..."+i);
        }
    }
}        

 

two. High concurrency, and thread-safe

High concurrency and thread-safe introduction

What is high concurrency: refers to a point in time, a large number of users (threads) simultaneously access the same resource
thread-safe: refers to a point in time, and after the occurrence of high data access of a "substandard actual character the data "have called thread-safety issues 

Multi-threaded operating mechanism

public class MyThread extends Thread { 
    @Override 
    public void run() { 
        for (int i = 0; i < 100; i++) { 
            System.out.println("i = " + i); 
        } 
    } 
}

public class Demo { 
    public static void main(String[] args) { 
        //1.创建两个线程对象 
        MyThread t1 = new MyThread(); 
        MyThread t2 = new MyThread(); 
        //2.启动两个线程 
        t1.start(); 
        t2.start(); 
	} 
}

Multi-threaded security issues - visibility

什么有可见性:
	当一个共性变量,被多个线程使用时,其中某个线程对共性变量进行了修改,对于其他线程来说并不是立刻可见的
        其他线程获取的值还是以前的副本(旧的值)
案例:
	public class MyThread extends Thread {
        //无论创建多个MyThread对象,他们共性一个静态变量a
        public static int a = 0;
        @Override
        public void run() {
            System.out.println("线程启动,休息2秒...");
            try { Thread.sleep(1000 * 2); } catch (InterruptedException e) { e.printStackTrace(); }
            System.out.println("将a的值改为1");
            a = 1;
            System.out.println("线程结束...");
        }
    }

	public class TestSafaDemo01 {
        public static void main(String[] args) {
            //1.启动线程
            MyThread t = new MyThread();
            t.start();
            //2.主线程继续
            while (true) {
                if (MyThread.a == 1) {
                    System.out.println("主线程读到了a = 1");
                }
            }
        }
    }

Multi-threaded security issues - orderliness

What is orderly:
    the code "rearrange" the extent not affect the results of the code
    if in the case of multi-threading, "rearrangement" might be the same code, the operation of the conclusions different results
    we want to ensure that in the case of multi-threaded, not code "rearrangement" to ensure that the code is ordered (do not use rearrangement !!) 

Multi-threaded security issues - atomicity

What Atomicity:
    thread a common variable, when ++ ++ divided into the two steps, the first value by 1 and then taken out to the common variable assignment
    if the value plus 1 is taken out, have not had time assignment, other threads being robbed CPU, we call this case having no atomic operation ++ 

three. volatile keyword

volatile is a keyword used to modify the member variables (static variables), he modified variables have visibility and order

volatile resolve visibility

public class MyThread extends Thread {
    //无论创建多个MyThread对象,他们共性一个静态变量a
    public volatile static int a = 0;
    @Override
    public void run() {
        System.out.println("线程启动...");
        try { Thread.sleep(1000 * 2); } catch (InterruptedException e) { e.printStackTrace(); }
        System.out.println("将a的值改为1");
        a = 1;
        System.out.println("线程结束...");
    }
}

public class TestSafaDemo01 {
    public static void main(String[] args) {
        //1.启动线程
        MyThread t = new MyThread();
        t.start();
        //2.主线程继续
        while (true) {
            if (MyThread.a == 1) {
                System.out.println("主线程读到了a = 1");
            }
        }
    }
}

volatile resolve orderliness

not solve the volatile atomicity

volatile不能解决原子性问题
public class MyThread extends Thread {
    public volatile static int a = 0;
    @Override
    public void run() {
        for (int i = 0; i < 10000; i++) {
            a++;
        }
        System.out.println("修改完毕!");
    }
}

public class TestSafeDemo {
    public static void main(String[] args) throws InterruptedException {
        MyThread t1 = new MyThread();
        MyThread t2 = new MyThread();

        t1.start(); //线程1 对a加了10000次
        t2.start(); // 线程2 对a加了 10000次
        Thread.sleep(1000);
        System.out.println("获取a最终值:" + MyThread.a);
        //总是不准确的。原因:两个线程访问a 的步骤不具有:原子性
    }
}

volatile role

a. solve variable visibility, once the variable is changed, all the variables to use threads will take to the latest value
b. orderliness of variables to solve, once variables plus volatile, the compiler does not code for this variable are rearrangements
c. process variable can not solve the atomic operation, the operation of the variables may still be interrupted by other threads  

four. - Atom

. What is the atom type A?
    Is the common types: class encapsulates atoms (such as int, Integer, double, Double), making the operation of the operation member atoms
b atomic action class.?
    to increase or decrease operation based atoms, guaranteed to be atomic, ensure that other threads will not be among "interrupted"
c atomic class what.?
    for example:
        AtomicInteger atomic class for int variable operating
        atomic class AtomicLong is long variable operating
        AtomicBoolean of boolean variable operation "atomic class";
Note: atomic class, not only can solve the atomicity, you can solve the ordered and visibility

In java.util.concurrent.atomic defines the next packet " variable " operation " atomic class ":
. 1) .java.util.concurrent.atomic.AtomicInteger : for int variable operation of " atom type ";
2) .java.util.concurrent.atomic.AtomicLong : for long variable operation of " atom type ";
. 3) .java.util.concurrent.atomic.AtomicBoolean : for boolean variable operation of " atom type ";

AtomicInteger class

a.AtomicInteger是什么?
    是对int类型变量进行操作的原子类
b.AtomicInteger的构造方法
    public AtomicInteger(int num);
c.AtomicInteger的成员方法
    public int getAndIncrement();//就相当于 变量++  
	public int incrementAndGet();//就相当于 ++变量 
    
d.使用AtomicInteger改写案例    
    public class MyThread extends Thread {
        public static AtomicInteger a = new AtomicInteger(0);
        @Override
        public void run() {
            for (int i = 0; i < 10000; i++) {
                a.getAndIncrement();//相当于 a++  先获取在自增1
            }
            System.out.println("修改完毕!");
        }
    }

	public class TestSafeDemo {
        public static void main(String[] args) throws InterruptedException {
            MyThread t1 = new MyThread();
            MyThread t2 = new MyThread();

            t1.start(); //线程1 对a加了10000次
            t2.start(); // 线程2 对a加了 10000次
            Thread.sleep(1000);
            System.out.println("获取a最终值:" + MyThread.a);
            //总是不准确的。原因:两个线程访问a 的步骤不具有:原子性
        }
    }

In Unsafe class, a call: compareAndSwapInt () method, this method several parameters:
var1 : Incoming AtomicInteger objects
var2 : AtommicInteger internal variable offset address
var5 : withdrawn before AtomicInteger values;
+ var4 var5 : Expected Results
This method uses a " compare and swap (Compare And Swap)" mechanism that would use var1 and var2 first acquisition memory
AtomicInteger in value, and then passed, the value of previously acquired var5 do some comparison, is a comparison of current memory value and the expected value
It is the same, if an agreement on the modifications to var5 + var4 , otherwise the cycle continues, get again AtomicInteger values, and then compare
Exchange, until the success of the exchange so far.
 
compareAndSwapInt () method is " thread-safe " is.
 
We assume that two threads alternately running and see how it works:
The initial AtomicInteger value 0
Thread A performs: var5 = this.getIntVolatile (var1, var2); result is obtained: 0
Thread A is suspended
Thread B performs: var5 = this.getIntVolatile (var1, var2); result is obtained: 0
Thread B executed: this.compareAndSwapInt (var1, var2, var5, var5 + var4)
Thread B successfully AtomicInteger value was changed to 1
Thread A recovery run, execute: this.compareAndSwapInt (var1, var2, var5, var5 + var4)
At this time, the thread A use var1 and var2 from AtomicInteger value acquired: 1 , and the incoming var5 is 0 , the comparison fails, the return
false , the loop continues.
Thread A performs: var5 = this.getIntVolatile (var1, var2); result is obtained: 1
Thread A execution: this.compareAndSwapInt (var1, var2, var5, var5 + var4)
At this time, the thread A use var1 and var2 from AtomicInteger value acquired: 1 , and the incoming var5 to 1 , the more successful, modifications thereof will be
Is var5 + var4 , i.e. 2 , the AtomicInteger value was changed to 2 , the end.
CAS mechanism is also known as: optimistic locking. Because most of the result of the comparison is to true , directly modified. Where only a small part of multithreading will
Leading to CAS failure, and the cycle again.

AtomicIntegerArray类

Conventional array type atomic operation: . 1) .java.util.concurrent.atomic.AtomicIntegetArray: for int -atomic array operation.
2) .java.util.concurrent.atomic.AtomicLongArray : for long -atomic array operation.
. 3) .java.utio.concurrent.atomic.AtomicReferenceArray : - Atom reference to the type of array operations.

Non-atomic array of classes there will be problems in multi-threaded

public class MyThread extends Thread {
    public static int[] intArray = new int[1000];//不直接使用数组

    @Override
    public void run() {
        for (int i = 0; i < intArray.length; i++) {
            intArray[i]++;
        }
    }
}

public class TestDemo01 {
    public static void main(String[] args) throws InterruptedException {
        //创建1000个线程,每个线程为数组的每个元素+1
        for (int i = 0; i < 1000; i++) {
            new MyThread().start();
        }

        Thread.sleep(1000 * 5);//让所有线程执行完毕
        System.out.println("主线程休息5秒醒来");
        for (int i = 0; i < MyThread.intArray.length; i++) {
            System.out.println(MyThread.intArray[i]);
        }
    }
}
打印结果:
	1000,1000,1000,999,1000,1000,1000,1000,....
有个别元素是小于1000的,因为int[]是非原子类数组,不能保存原子性!!!

The use of atomic array of classes to ensure atomicity, to solve the problem

public class MyThread extends Thread {
    public static int[] intArray = new int[1000];//不直接使用数组
    public static AtomicIntegerArray arr = new AtomicIntegerArray(intArray);
    @Override
    public void run() {
//        for (int i = 0; i < intArray.length; i++) {
//            intArray[i]++;
//        }
        for (int i = 0; i < arr.length(); i++) {
            arr.addAndGet(i, 1);//将i位置上的元素 + 1,相当于 ++数组[i]
        }

    }
}

public class TestDemo01 {
    public static void main(String[] args) throws InterruptedException {
        //创建1000个线程,每个线程为数组的每个元素+1
        for (int i = 0; i < 1000; i++) {
            new MyThread().start();
        }

        Thread.sleep(1000 * 5);//让所有线程执行完毕
        System.out.println("主线程休息5秒醒来");
//        for (int i = 0; i < MyThread.intArray.length; i++) {
//            System.out.println(MyThread.intArray[i]);
//        }
        for (int i = 0; i < MyThread.arr.length(); i++) {
            System.out.println(MyThread.arr.get(i));
        }
    }
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Published 103 original articles · won praise 15 · views 270 000 +

Guess you like

Origin blog.csdn.net/u010581811/article/details/104882590