Java多线程编程概述
Java多线程的安全问题
Java多线程同步
Java多线程间的通信
Java线程Lock
Java多线程管理
保障线程安全的设计技术
Java锁的优化及注意事项
Java多线程集合
【Java多线程】单例模式与多线程

Java多线程同步方法

package com.wkcto.intrinsiclock;

/**
 * synchronized同步实例方法
 *      把整个方法体作为同步代码块
 *      默认的锁对象是this对象
 * Author: 老崔
 */
public class Test05 {
    public static void main(String[] args) {
        //先创建Test01对象,通过对象名调用mm()方法
        Test05 obj = new Test05();

        //一个线程调用mm()方法
        new Thread(new Runnable() {
            @Override
            public void run() {
                obj.mm();       //使用的锁对象this就是obj对象
            }
        }).start();

        //另一个线程调用mm22()方法
        new Thread(new Runnable() {
            @Override
            public void run() {
                obj.mm22();       //使用的锁对象this也是obj对象, 可以同步
//                new Test05().mm22();       //使用的锁对象this是刚刚new创建的一个新对象,不是同一个锁对象不能同步
            }
        }).start();

    }

    //定义方法,打印100行字符串
    public void mm(){
        synchronized ( this ) {     //经常使用this当前对象作为锁对象
            for (int i = 1; i <= 100; i++) {
                System.out.println(Thread.currentThread().getName() + " --> " + i);
            }
        }
    }

    //使用synchronized修饰实例方法,同步实例方法, 默认this作为锁对象
    public synchronized void mm22(){
            for (int i = 1; i <= 100; i++) {
                System.out.println(Thread.currentThread().getName() + " --> " + i);
            }
    }
}

package com.wkcto.intrinsiclock;

/**
 * synchronized同步静态方法
 *      把整个方法体作为同步代码块
 *      默认的锁对象是当前类的运行时类对象, Test06.class, 有人称它为类锁
 * Author: 老崔
 */
public class Test06 {
    public static void main(String[] args) {
        //先创建Test01对象,通过对象名调用mm()方法
        Test06 obj = new Test06();

        //一个线程调用m1()方法
        new Thread(new Runnable() {
            @Override
            public void run() {
                obj.m1();       //使用的锁对象是Test06.class
            }
        }).start();

        //另一个线程调用sm2()方法
        new Thread(new Runnable() {
            @Override
            public void run() {
                Test06.sm2();    //使用的锁对象是Test06.class
            }
        }).start();

    }

    //定义方法,打印100行字符串
    public void m1(){
        //使用当前类的运行时类对象作为锁对象,可以简单的理解为把Test06类的字节码文件作为锁对象
        synchronized ( Test06.class ) {
            for (int i = 1; i <= 100; i++) {
                System.out.println(Thread.currentThread().getName() + " --> " + i);
            }
        }
    }

    //使用synchronized修饰静态方法,同步静态方法, 默认运行时类Test06.class作为锁对象
    public synchronized static  void sm2(){
            for (int i = 1; i <= 100; i++) {
                System.out.println(Thread.currentThread().getName() + " --> " + i);
            }
    }
}
package com.wkcto.intrinsiclock;

/**
 * 同步方法与同步代码块如何选择
 *  同步方法锁的粒度粗, 执行效率低, 同步代码块执行效率高
 *
 * Author: 老崔
 */
public class Test07 {
    public static void main(String[] args) {
        Test07 obj = new Test07();

        new Thread(new Runnable() {
            @Override
            public void run() {
                obj.doLongTimeTask();
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                obj.doLongTimeTask();
            }
        }).start();
    }

    //同步方法, 执行效率低
    public synchronized void doLongTimeTask(){
        try {
            System.out.println("Task Begin");
            Thread.sleep(3000);         //模拟任务需要准备3秒钟


                System.out.println("开始同步");
                for(int i = 1; i <= 100; i++){
                    System.out.println(Thread.currentThread().getName() + "-->" + i);
                }

            System.out.println("Task end");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    //同步代码块,锁的粒度细, 执行效率高
    public void doLongTimeTask2(){
        try {
            System.out.println("Task Begin");
            Thread.sleep(3000);         //模拟任务需要准备3秒钟

            synchronized (this){
                System.out.println("开始同步");
                for(int i = 1; i <= 100; i++){
                    System.out.println(Thread.currentThread().getName() + "-->" + i);
                }
            }
            System.out.println("Task end");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}