Java多线程编程2

Thread类

Thread类综合了Java程序中一个线程需要拥有的属性和方法,其构造方法如下:

               public Thread();
               public Thread (ThreadGroup group,Runnable target,String name);     
               public Thread(Runnable target);
               public Thread(Runnable target,String name);
               public Thread(String name);
               public Thread(ThreadGroup group,Runnable target);
               public Thread(ThreadGroup group,String name); 
  • 继承Thread类实现多线程     
    需要重写run方法实现线程的任务.需要注意的是,程序中不要直接调用此方法,而是调用线程对象的start()方法启动线程,让其进入可调度状态,线程获得调度自动执行run()方法.
  • 实现Runnable接口编写多线程
    通过 Thread 类的构造函数public Thread(Runnable target)可以将一个Runnable 接口对象传递给线程,线程在调度时将自动调用Runnable 接口对象的run方法。

使用线程

若想有效使用多线程代码,要对监视器和锁有些基本的认识。你需要知道的要点如下。
• 同步是为了保护对象的状态和内存,而不是代码。
• 同步是线程间的协助机制。一个缺陷就可能破坏这种协助模型,导致严重的后果。
• 获取监视器只能避免其他线程再次获取这个监视器,而不能保护对象。
• 即便对象的监视器锁定了,不同步的方法也能看到(和修改)不一致的状态。
• 锁定 Object[] 不会锁定其中的单个对象。
• 基本类型的值不可变,因此不能(也无需)锁定。
• 接口中声明的方法不能使用 synchronized 修饰。
• 内部类只是语法糖,因此内部类的锁对外层类无效(反过来亦然)。
• Java 的锁可重入(reentrant)。这意味着,如果一个线程拥有一个监视器,这个线程遇到具有同一个监视器的同步代码块时,可以进入这个代码块。

wait() 和 notify() 方法必须在 synchronized 修饰的方法或代码块中使用,
因为只有临时把锁放弃,这两个方法才能正常工作。

线程调度与优先级(多线程的特性: 随机性)

Java采用抢占式调度策略,下面几种情况下,当前线程会放弃CPU:

  1. 当前时间片用完;
  2. 线程在执行时调用了yield()sleep()方法主动放弃;
  3. 进行I/O 访问,等待用户输入,导致线程阻塞;或者为等候一个条件变量,线程调用wait方法;
  4. 有高优先级的线程参与调度。
  • 线程的优先级用数字来表示,范围从1~10。主线程的默认优先级为5
    //三个常用的优先级
    Thread.MIN_PRIORITY=1          
    Thread.NORM_PRIORITY=5     
    Thread.MAX_PRIORITY=10

线程资源的同步处理

临界资源问题
Java对于多线程的安全问题提供了专业的解决方式: 就是同步代码块, 主要用来处理线程间的互斥问题.

Java多线程编程2_第1张图片

synchronized(对象) {
    需要被同步的代码
  }

  • 对象如同锁,持有锁的线程可以在同步中执行.
  • 没有持有锁的线程及时获取cpu的执行权,也进不去,因为没有获取锁.

同步的前提:

  1. 必须要有两个或者以上的线程
  2. 必须要多个线程使用同一个锁

好处:解决了多线程的安全问题
弊端:多个线程需要判断锁,较为消耗资源.

同步函数使用的是哪个锁:
函数需要被对象调用,那么函数都有一个所属对象的引用.就是this. 所以同步函数使用的锁是this锁.静态函数使用的是该方法所在类的字节码文件对象.

在使用synchronized时有一个误区, 就是被保护的代码块过多. 比如一个方法中只有少数几行代码访问共享变量, 却把整个方法声明为synchronized. 这样会影响程序的性能, 正确的做法是把需要同步的代码块用synchronized代码块包围即可.

避免死锁

多个线程相互等待对方释放持有的锁,并且在得到对方锁之前不释放自己的锁.(自己能写一个死锁代码)

你可能感兴趣的:(Java多线程编程2)