一、前置知识
【普通】创建线程的两种方式
- new Thread():在调用该线程的start()方法之后,会直接执行他的run() 方法。
- 实现Runnable接口:该方式首先会将 new MyThread1() 对象作为成员变量存在Thread的成员变量target中,然后在调用start() 方法后,会调用target中的run() 方法。
public class ThreadDemo {
public static void main(String[] args) {
// 1.方式一
new MyThread("我的线程").start();
// 2.方式二
new Thread(new MyThread1()).start();
}
}
class MyThread extends Thread {
MyThread(String name) {
super(name);
}
@SneakyThrows
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "正在执行~");
Thread.sleep(1000);
}
}
class MyThread1 implements Runnable {
@SneakyThrows
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "正在执行~");
Thread.sleep(1000);
}
}
二、不同场景下作用范围不同
1、没有synchronized修饰,多线程并发
public class SynchronizedDemo {
public static void main(String[] args) {
NoneSyncDemo noneSyncDemo = new NoneSyncDemo();
new Thread(noneSyncDemo).start();
new Thread(noneSyncDemo).start();
}
}
class NoneSyncDemo implements Runnable {
@Override
public void run() {
for (int i = 0; i < 3; i++) {
try {
System.out.println(Thread.currentThread().getName() + ":" + i);
TimeUnit.MILLISECONDS.sleep(20);
} catch (Throwable e) {
e.printStackTrace();
}
}
}
}
2、 synchronized修饰代码块(对象),当传入的对象相同,线程串行执行
public class SynchronizedDemo1 {
public static void main(String[] args) throws InterruptedException {
// 加锁有效
SyncBlockDemo syncBlockDemo = new SyncBlockDemo();
new Thread(syncBlockDemo).start();
new Thread(syncBlockDemo).start();
Thread.sleep(1000);
System.out.println("----------");
new Thread(new SyncBlockDemo()).start();
new Thread(new SyncBlockDemo()).start();
}
}
class SyncBlockDemo implements Runnable {
@Override
public void run() {
synchronized (this) {
for (int i = 0; i < 3; i++) {
try {
System.out.println(Thread.currentThread().getName() + ":" + i);
TimeUnit.MILLISECONDS.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
3、synchronized修饰代码块(类对象),多有通过该 SyncClassDemo 类实现的线程,都要串行执行。
public class SynchronizedDemo2 {
public static void main(String[] args) throws InterruptedException {
// 加锁有效
SyncClassDemo syncClassDemo = new SyncClassDemo();
new Thread(syncClassDemo).start();
new Thread(syncClassDemo).start();
Thread.sleep(1000);
System.out.println("----------------------------------");
// 加锁有效
new Thread(new SyncClassDemo()).start();
new Thread(new SyncClassDemo()).start();
}
}
class SyncClassDemo implements Runnable {
@Override
public void run() {
synchronized (SyncClassDemo.class) {
for (int i = 0; i < 3; i++) {
try {
System.out.println(Thread.currentThread().getName() + ":" + i);
TimeUnit.MILLISECONDS.sleep(20);
} catch (Throwable e) {
e.printStackTrace();
}
}
}
}
}
4、synchronized修饰方法,成员方法,是对象级别的锁,使用相同的 SyncMethodDemo 类的对象实现的多线程,需要串行执行。
public class SynchronizedDemo3 {
public static void main(String[] args) throws InterruptedException {
// 加锁有效
SyncMethodDemo syncMethodDemo = new SyncMethodDemo();
new Thread(syncMethodDemo).start();
new Thread(syncMethodDemo).start();
Thread.sleep(1000);
System.out.println("----------------------------------");
// 加锁无效
new Thread(new SyncMethodDemo()).start();
new Thread(new SyncMethodDemo()).start();
}
}
class SyncMethodDemo implements Runnable {
@Override
public synchronized void run() {
for (int i = 0; i < 3; i++) {
try {
System.out.println(Thread.currentThread().getName() + ":" + i);
TimeUnit.MILLISECONDS.sleep(20);
} catch (Throwable e) {
e.printStackTrace();
}
}
}
}
5、synchronized修饰静态方法,类方法,是类级别的锁,使用SyncMethodDemo 类的不同实现对象实现的多线程,需要串行执行。
public class SynchronizedDemo4 {
public static void main(String[] args) throws InterruptedException {
// 加锁有效
SyncStaticMethodDemo syncStaticMethodDemo = new SyncStaticMethodDemo();
new Thread(syncStaticMethodDemo).start();
new Thread(syncStaticMethodDemo).start();
Thread.sleep(1000);
System.out.println("----------------------------------");
// 加锁有效
new Thread(new SyncStaticMethodDemo()).start();
new Thread(new SyncStaticMethodDemo()).start();
}
}
class SyncStaticMethodDemo implements Runnable {
@Override
public void run() {
method();
}
public synchronized static void method() {
for (int i = 0; i < 3; i++) {
try {
System.out.println(Thread.currentThread().getName() + ":" + i);
TimeUnit.MILLISECONDS.sleep(20);
} catch (Throwable e) {
e.printStackTrace();
}
}
}
}