程序中用大括号括起来的代码叫代码块.

1. 局部代码块

局部代码块是定义在方法或语句中

  • 特点:
    • 以”{}”划定的代码区域,此时只需要关注作用域的不同即可。
    • 方法和类都是以代码块的方式划定边界的。
  • 作用:可以限定变量的声明周期.

    1. class Demo{
    2. public static void main(String[] args) {
    3. {
    4. int x = 1;
    5. System.out.println("普通代码块" + x);
    6. }
    7. int x = 99;
    8. System.out.println("代码块之外" + x);
    9. }
    10. }

    2. 构造代码块

    构造代码块是定义在类中成员位置的代码块
    特点:

  • 优先于构造方法执行, 构造代码块用于执行所有对象均需要的初始化动作

  • 每创建一个对象均会执行一次构造代码块。

    1. public class Person {
    2. private String name;
    3. private int age;
    4. //构造代码块
    5. {
    6. System.out.println("构造代码块执行了");
    7. }
    8. Person(){
    9. System.out.println("Person无参数的构造函数执行");
    10. }
    11. }

    3. 静态代码块

    静态代码块是定义在成员位置,使用static修饰的代码块。
    特点:

  • 它优先于main方法中的代码执行、优先于构造代码块执行,当以任意形式第一次使用到该类时执行。

  • 该类不管创建多少对象,静态代码块只执行一次。

作用: 可用于给静态变量赋值,用来给类进行初始化。

  1. public class Person {
  2. private String name;
  3. private int age;
  4. //静态代码块
  5. static{
  6. System.out.println("静态代码块执行了");
  7. }
  8. }

4. synchronized同步代码块

使用synchronized声明的方法在某些情况下是有弊端的,比如A线程调用同步的方法执行一个长时间的任务,那么B线程就必须等待比较长的时间才能执行,这种情况可以使用synchronized代码块去优化代码执行时间,也就是通常所说的减少锁的粒度

  1. public class Optimize {
  2. public void doLongTimeTask(){
  3. try {
  4. System.out.println("当前线程开始:" + Thread.currentThread().getName() +
  5. ", 正在执行一个较长时间的业务操作,其内容不需要同步");
  6. Thread.sleep(2000);
  7. synchronized(this){
  8. System.out.println("当前线程:" + Thread.currentThread().getName() +
  9. ", 执行同步代码块,对其同步变量进行操作");
  10. Thread.sleep(1000);
  11. }
  12. System.out.println("当前线程结束:" + Thread.currentThread().getName() +
  13. ", 执行完毕");
  14. } catch (InterruptedException e) {
  15. e.printStackTrace();
  16. }
  17. }
  18. public static void main(String[] args) {
  19. final Optimize otz = new Optimize();
  20. Thread t1 = new Thread(new Runnable() {
  21. @Override
  22. public void run() {
  23. otz.doLongTimeTask();
  24. }
  25. },"t1");
  26. Thread t2 = new Thread(new Runnable() {
  27. @Override
  28. public void run() {
  29. otz.doLongTimeTask();
  30. }
  31. },"t2");
  32. t1.start();
  33. t2.start();
  34. }
  35. }

当两个并发线程访问同一个对象object中的synchronized(this)同步代码块时,一段时间内只能有一个线程被执行,另一个线程必须等待当前线程执行完这个同步代码块以后才能执行该代码块。当一个线程访问object的一个synchronized同步代码块时,另一个线程仍然可以执行该object对象中的非synchronized(this)同步代码块。

synchronized 关键字可以修饰方法,这个方法叫做synchronized同步方法。它的作用如下:

  1. 对其他synchronized同步方法或synchronized(this)同步代码块呈阻塞状态
  2. 同一时间只有一个线程可以执行synchronized同步方法中的代码。

synchronized 关键字也可以修饰代码块,它有如下两类:

  1. synchronized(this)同步代码块:
    1. 对其他synchronized同步方法或synchronized(this)同步代码块呈阻塞状态。
    2. 同一时间只有一个线程可以执行synchronized(this)同步代码块中的代码。
  2. synchronized(非this)代码块:
    1. synchronized(非this)代码块的程序与同步方法和synchronized(this)同步代码块是异步的。不与其他锁this的同步方法争抢this锁,则可以大大提高运行效率。
    2. 使用synchronized(非this对象x)同步代码块 进行同步操作时,对象监视器必须是同一个对象。如果不是同一个对象监视器,运行的结果就是异步调用了,就会交叉运行。