zoukankan      html  css  js  c++  java
  • 多线程

    先说一下如何学习一门语言和技术

    1. 了解语言背景,特点.

    2. 语法

    3. 通用小程序

    4. 函数和对象

    5. 第三方类库,插件组件,框架

    6. 开发项目

    实现多线程的两种方式:

    1. 继承Thread类
      1. 自定义MyThread继承Thread
      2. 在MyThread中重写run()方法
      3. 创建MyThread类对象
      4. 启动线程对象
      5. 实例:创建SellTicket.java和SellTicketDemo.java类
         1 public class SellTicket implements Runnable {
         2 //定义100张票
         3     private int tickets=100;
         4     //创建锁
         5     private Object obj=new Object();
         6     @Override
         7     public void run() {
         8         synchronized(obj){
         9             while(true){
        10                 if(tickets>0){
        11                     try {
        12                         Thread.sleep(100);
        13                     } catch (InterruptedException e) {
        14                         e.printStackTrace();
        15                     }
        16                     System.out.println(Thread.currentThread().getName()+"正在出售"+(tickets--)+"张票");
        17                 }
        18             }
        19         }
        20     }
        21 }

        SellTicketDemo.java类:

         1 public class SellTicketDemo {
         2  public static void main(String[] args) {
         3     //创建资源对象
         4      SellTicket st1=new SellTicket();
         5      //当前时间,在这里没有意义
         6      SimpleDateFormat df = new SimpleDateFormat("EEE, MMM d, ''yy");  
         7      System.out.println(df.format(System.currentTimeMillis()));   
         8      //创建3个线程对象,传递Myrunable类的对象.
         9      Thread t1=new Thread(st1, "窗口1");
        10      Thread t2=new Thread(st1,"窗口2");
        11      Thread t3=new Thread(st1,"窗口3");
        12      
        13      t2.start();
        14      t1.start();
        15      t3.start();
        16 }
        17 }
    2. 实现Runable接口:
      1. 自定义MyRunable实现Runable接口;
      2. 在MyRunable里面重写run()方法;
      3. 创建MyRunable类的对象;
      4. 创建Thread类的对象,并把3中对象作为构造参数 传递.
            public static void main(String[] args) {
                 new Thread(new Thread1()).start();
                 try {
                     Thread.sleep(100);
                 } catch (InterruptedException e) {
                     e.printStackTrace();
                 }
                 new Thread(new Thread2()).start();         
            }
            
            /*
             * Thread1实现Runable
             */
            private static class Thread1 implements Runnable
            {
                 @Override
                 public void run() {
                //由于这里的Thread1和下面的Thread2内部run方法要用同一对象作为监视器,
               //我们这里不能用this,因为在Thread2里面的this和这个Thread1的this不是同一个对象。我们用MultiThread.class这个字节码对象,当前虚拟机里引用这个变量时,指向的都是同一个对象。
                synchronized (MultiThread.class) {
                System.out.println("enter thread1...");
                System.out.println("thread1 is waiting");
                try {
                 //释放锁有两种方式,第一种方式是程序自然离开监视器的范围,
                 //也就是离开了synchronized关键字管辖的代码范围,
                //另一种方式就是在synchronized关键字管辖的代码内部调用监视器对象的wait方法。这里,使用wait方法释放锁。
                 MultiThread.class.wait();
                 } catch (InterruptedException e) {
                  e.printStackTrace();
                  }
                   System.out.println("thread1 is going on...");
                   System.out.println("thread1 is being over!");             
                     }
                 }
            }
            
            /*
             * Thread2
             */
            private static class Thread2 implements Runnable
            {
                 @Override
                 public void run() {
                     synchronized (MultiThread.class) {
                          System.out.println("enter thread2...");
                          System.out.println("thread2 notify other thread can release wait status..");
                  //由于notify方法并不释放锁, 即使thread2调用下面的sleep方法休息了10毫秒,
                 //但thread1仍然不会执行,因为thread2没有释放锁,所以Thread1无法得不到锁。
                          MultiThread.class.notify();
                          System.out.println("thread2 is sleeping ten millisecond...");
                          try {
                               Thread.sleep(10);
                          } catch (InterruptedException e) {
                               e.printStackTrace();
                          }
                          System.out.println("thread2 is going on...");
                          System.out.println("thread2 is being over!");
                     }
                 }
            }    
        
    • 为什么要有两种方式:

      • 实现Runable接口解决了java单继承的局限性,适合多个相同程序的代码去处理同一个资源的情况 ,把线程同程序代码和数据分离,较好 的体现了面向 对象的设计思想.

    线程安全的原因:

    1. 是多线程;

    2. 共享数据;

    3. 有多条语句操作数据

    解决方案:就是破坏线程不安全的条件,非要在多线程下操作共享数据就只能破坏第三个条件了,把多条语句操作共享数据的代码包成一个代码块,让某个线程在执行 的时候别人不能执行,这里java给我们提供的同步机制:synchronized

    1 synchronized(对象){//同步的根本就在对象,该对象如同锁,多个线程同一把锁,
    2     代码块
    3 }

    同步的弊端 :当线程特别多时,因为每一个锁都会去判断同步上的锁,这是很浪费资源的,无形中降低了程序运行的效率.

    线程安全的类有:

    1 1 //线程安全的类
    2 2 StringBuffer sb =new StringBuffer();
    3 3 Vector<String> v=new Vector<String>)();
    4 4 Hashtable<String,String> h=new Hashtable<String,String>();

      原因:就是在这些类中实现了Runable接口,具备了线程安全的特性

    使用如下代码可以使类具备线程安全:

    1 //线程安全
    2 List<String> li=Collections.synchronizedList(new ArrayList<String>());
  • 相关阅读:
    Cognitive Radio Cognitive Network Simulator (NS3 based)
    RCU(Read-Copy Update)synchronize原理分析
    英雄黑客:一个试图提高物联网安全性的“义务警员”
    Android NDK放弃GCC,全面转向Clang
    Why is FreeBSD deprecating GCC in favor of Clang/LLVM?
    (Low Level Virtual Machine) LLVM 与 Clang介绍
    RMS谈GCC、LLVM和Copyleft
    LLVM和Clang背后的故事
    FEP: 测试 lineage, 获得 CPU, MEMORY 统计信息
    以wifi-example-sim.cc为例说明NS3统计数据模型
  • 原文地址:https://www.cnblogs.com/52haiyan/p/9441997.html
Copyright © 2011-2022 走看看