黑马程序员——多线程2多线程安全性的探讨

来源:互联网 发布:vb中"clear"是什么意思 编辑:程序博客网 时间:2024/05/16 08:23
------- android培训java培训、期待与您交流! ----------

一、实现Runnable接口

 1.定义类实现Runnable接口。
2.覆盖接口中的run方法,将线程的任务代码封装到run方法中。
3.通过Thread类创建线程对象,并将Runnable接口的子类对象作为Thread类的构造函数的参数进行传递。为什么?

因为线程的任务都封装在Runnable接口子类对象的run方法中。所以要在线程对象创建时就必须明确要运行的任务。
 4.调用线程对象的start方法开启线程。


实现Runnable接口的好处:
 1.将线程的任务从线程的子类中分离出来,进行了单独的封装,按照面向对象的思想将任务封装成对象。
 2.避免了Java单继承的局限性。所以,创建线程的第二种方式较为常用。

示例:

[java] view plaincopy
  1. class Demo implements Runnable{  
  2.         public void run(){  
  3.             show();  
  4.         }  
  5.         public void show(){  
  6.             for(int x = 0; x < 20; x++){  
  7.           System.out.println(Thread.currentThread().getName() + "..." + x);  
  8.             }  
  9.         }  
  10. }  
  11. class ThreadDemo {  
  12.     public static void main(String[] args){  
  13.             Demo d = new Demo();  
  14.             Thread t1 = new Thread(d);  
  15.             Thread t2 = new Thread(d);  
  16.             t1.start();  
  17.             t2.start();  
  18.     }  
  19. }  
程序运行结果如下:

二、线程安全问题:

线程安全问题产生的原因:

1.多个线程在操作共享的数据。
 2.操作共享数据的线程代码有多条。
 当一个线程在执行操作共享数据的多条代码过程中,其他线程参与了运算,就会导致线程安全问题的产生。

*线程安全问题的解决方案:

思路:
 就是将多条操作共享数据的线程代码封装起来,当有线程在执行这些代码的时候,其他线程不可以参与运算。必须要当前线程把这些代码都执行完毕后,其他线程才可以参与运算。
 在java中,用同步代码块就可以解决这个问题。
 同步代码块的格式:
 synchronized(对象){
 需要被同步的代码;
 }


同步的好处:解决了线程的安全问题。
 同步的弊端:当线程相当多时,因为每个线程都会去判断同步上的锁,这是很耗费资源的,无形中会降低程序的运行效率。
同步的前提:必须有多个线程并使用同一个锁。

 利用同步代码块解决安全问题案例:

需求:储户,两个,每个都到银行存钱,每次存100,共存三次。

代码:

[java] view plaincopy
  1. class Bank{  
  2.        private int sum ;  
  3.        public void add(int num){  
  4.        synchronized(this){  
  5.        sum = sum + num;  
  6.        System.out.println("sum = " + sum);  
  7.        }  
  8.        }  
  9.     }  
  10. class Cus implements Runnable{  
  11.     private Bank b = new Bank();  
  12.     public void run(){  
  13.         for(int x = 0; x < 3; x++){  
  14.             b.add(100);  
  15.         }  
  16.     }  
  17. }  
  18. public class BankDemo {  
  19.     public static void main(String[] args){  
  20.         Cus c = new Cus();  
  21.         Thread t1 = new Thread(c);  
  22.         Thread t2 = new Thread(c);  
  23.         t1.start();  
  24.         t2.start();  
  25.     }  
  26. }  
程序运行结果为:


*安全问题的另一种解决方案:同步代码块

  格式:在函数上加上synchronized修饰符即可。

示例:

[java] view plaincopy
  1. class Bank{  
  2.        private int sum;  
  3.        public synchronized void add(int num){  
  4.        sum = sum+num;  
  5.        System.out.println("sum="+sum);  
  6.     }  
  7. }  
程序运行结果为:

注意:

同步函数和同步代码块的区别:
 1.同步函数的锁是固定的this。
2.同步代码块的锁是任意的对象。
 *建议使用同步代码块。
 由于同步函数的锁是固定的this,同步代码块的锁是任意的对象,那么如果同步函数和同步代码块都使用this作为锁,就可以实现同步。

0 0
原创粉丝点击