The basic use of multithreading

There are two ways to create threads

  1. Thread class inheritance

    public class MyThread extends Thread{
        @Override
        public void run(a) {
            System.out.println(getName()+"--->run");
        }
    
        public static void main(String[] args) throws InterruptedException {
            Thread a = new MyThread();
            Thread b = newMyThread(); a.start(); b.start(); a.join(); b.join(); }}Copy the code
  2. Implement the Runnable interface

    public static void main(String[] args) {
        Runnable runnable = new Runnable() {
            @Override
            public void run(a) {
                System.out.println("i'm runnable"); }};new Thread(runnable).start();
    }
    Copy the code

    Abbreviations:

    public static void main(String[] args) {
        new Thread(()->{
            System.out.println("i'm simple");
        }).start();
    }
    Copy the code

Thread synchronization

If synchronization is not set

class MyRunnableImpl implements Runnable{
    private int x = 0;
    @Override
    public void run(a) {
        for(int i =0; i<10000; i++){ x = x+1;
            x = x-1; }}public int getX(a) {
        returnx; }}public class SyncTest {
    public static void main(String[] args) throws InterruptedException {
        MyRunnableImpl runnable = new MyRunnableImpl();
        Thread thread = new Thread(runnable);
        Thread thread2 = newThread(runnable); thread.start(); thread2.start(); thread.join(); thread2.join(); System.out.println(runnable.getX()); }}Copy the code

The running result of this program: 28

But according to the program’s logic, it should be 0, and the reason it’s not 0 is because there’s no synchronization

Set synchronization using the synchronized keyword

class MyRunnableImpl implements Runnable{
    private int x = 0;
    @Override
    public void run(a) {
        for(int i =0; i<10000; i++){synchronized (this){
                x = x+1;
                x = x-1; }}}public int getX(a) {
        returnx; }}public class SyncTest {
    public static void main(String[] args) throws InterruptedException {
        MyRunnableImpl runnable = new MyRunnableImpl();
        Thread thread = new Thread(runnable);
        Thread thread2 = newThread(runnable); thread.start(); thread2.start(); thread.join(); thread2.join(); System.out.println(runnable.getX()); }}Copy the code

The run result is 0

The synchronized keyword can also be added to a function to indicate that the contents of the function body are locked

class MyRunnableImpl implements Runnable{
    private int x = 0;
    @Override
    public synchronized void run(a) {
        for(int i =0; i<10000; i++){ x = x+1;
                x = x-1; }}public int getX(a) {
        returnx; }}public class SyncTest {
    public static void main(String[] args) throws InterruptedException {
        MyRunnableImpl runnable = new MyRunnableImpl();
        Thread thread = new Thread(runnable);
        Thread thread2 = newThread(runnable); thread.start(); thread2.start(); thread.join(); thread2.join(); System.out.println(runnable.getX()); }}Copy the code

Synchronized operations are not required

The JVM specification defines several atomic operations:

  • Basic type (longanddoubleExcept for), for example:int n = m;
  • Reference type assignment, for example:List<String> list = anotherList.

Long and double are 64-bit data. The JVM does not specify whether 64-bit assignment is an atomic operation, but x64 JVMS implement long and double assignments as atomic operations.

Statements that operate on a single atom do not need to be synchronized

Java multithreading – Threads communicate wait and Notify