其他分享
首页 > 其他分享> > 创建多线程两种方式参考例子(synchronized)

创建多线程两种方式参考例子(synchronized)

作者:互联网

  线程窗口买票例子(存在线程安全问题)   开发中:优先选择Runnable接口的方式 原因:1.实现的方式没有类的单继承性的局限性    2.实现的方式更适合来处理多个线程有共享数据的情况 二者联系:public class Thread implements Runnable 相同点:两种都要重写run(),将线程要执行的逻辑声明再run()中。   创建线程的两种方式选择   方式一:继承Thread类  
public class WindowsTest {
    public static void main(String[] args) {
        // 方式一:继承于Thread类测试
        Window1 w1 = new Window1();
        Window1 w2 = new Window1();
        Window1 w3 = new Window1();
 
        w1.setName("窗口一");
        w2.setName("窗口二");
        w3.setName("窗口三");
 
        w1.start();
        w2.start();
        w3.start();
    }
}
 
class Window1 extends Thread {
    // 使用了static修饰多个线程调用也是只有100张票
    private static int ticket = 100;
  // 重写run()方法
    @Override
    public void run() {
        while (true) {
            if (ticket > 0) {
                System.out.println(Thread.currentThread().getName() + ":买票,票号为:" + ticket);
                ticket--;
            }else {
                break;
            }
        }
    }
}

 

方式二:实现Runaable接口

 

public class WindowsTest {
    public static void main(String[] args) {
 
        // 方式二:实现Runnable接口测试
        Window w = new Window();
        Thread t1 = new Thread(w);
        Thread t2 = new Thread(w);
        Thread t3 = new Thread(w);
 
        t1.setName("窗口一");
        t2.setName("窗口二");
        t3.setName("窗口三");
 
        t1.start();
        t2.start();
        t3.start();
 
    }
}
 
class Window implements Runnable {
 
    private int ticket = 100;
  // 重写run()方法
    @Override
    public void run() {
        while (true) {
            if (ticket > 0) {
                System.out.println(Thread.currentThread().getName() + ":买票,票号为:" + ticket);
                ticket--;
            }else {
                break;
            }
        }
    }
}

 

 以下解决线程安全问题  

 方式一:同步代码块

 说明:1.操作共享数据代码,即为需要被同步的代码     2.共享数据:多个线程共同操作的变量。比如:ticket就是共享数据     3.同步监视器,俗称:锁。任何一个类的对象,都可以充当锁。          (要求:多个线程必须公用同一把锁。)

 

 继承方式:

 

public class WindowsTest {
    public static void main(String[] args) {
        // 方式一:继承于Thread类测试         
        Windows w1 = new Windows();
        Windows w2 = new Windows();
        Windows w3 = new Windows();               

   // 此时创建了多个对象执行 w1.setName("窗口1"); w2.setName("窗口2"); w3.setName("窗口3"); w1.start(); w2.start(); w3.start(); } } class Windows extends Thread { // 使用了static修饰多个线程调用也是只有100张票 private static int ticket = 100; // 这里需要static来保证锁的唯一性(调用时可能创建了多个对象调用) @Override public void run() { while (true) { synchronized (Windows.class) { if (ticket > 0) {
            // 延时 try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + ":买票,票号为:" + ticket); ticket--; }else { break; } } } } }   

 

实现方式:

 

public class WindowsTest {
    public static void main(String[] args) {
     // 方式二:实现Runnable接口
        Windows w = new Windows();
     // 这边共用了一个对象 Thread t1 = new Thread(w); Thread t2 = new Thread(w); Thread t3 = new Thread(w); t1.setName("窗口一"); t2.setName("窗口二"); t3.setName("窗口三"); t1.start(); t2.start(); t3.start(); } } class Windows implements Runnable { private int ticket = 100; @Override public void run() { while (true) { synchronized (windows.class) { if (ticket > 0) {
            // 延时 try { Thread.sleep(100); }catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + ":买票,票号为:" + ticket); ticket--; }else { break; } } } } }

 

方式二:同步方法
如果操作共享数据的代码完整的声明在一个方法中,我们不妨将此方法声明同步的。

 

继承方式:

 

// 继承于Thread类
public class WindowsTest {
    public static void main(String[] args) {
        Windows w1 = new Windows();
        Windows w2 = new Windows();
        Windows w3 = new Windows();
         
        w1.setName("窗口一");
        w2.setName("窗口二");
        w3.setName("窗口三");
         
        w1.start();
        w2.start();
        w3.start();
    }
}
 
class Windows extends Thread{
     
    private static int ticket = 100;
     
    @Override
    public void run() {
        while (true) {
       // 调用方法 show(); } } // 创建一个方法,将共享数据声明在里方法里 private static synchronized void show() { // private synchronized void show() //同步监视器 w1,w2,w3 if (ticket > 0) { try { Thread.sleep(100); }catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + ":买票,票号为:" + ticket); ticket--; } } }

 

实现方式:

 

// 实现Runnable接口
public class WindowsTest1 {
    public static void main(String[] args) {
        Windows w = new Windows();
         
        Thread t1 = new Thread(w);
        Thread t2 = new Thread(w);
        Thread t3 = new Thread(w);
         
        t1.setName("窗口一");
        t2.setName("窗口二");
        t3.setName("窗口三");
         
        t1.start();
        t2.start();
        t3.start();
    }
}
 
class Windows implements Runnable{
     
    private int ticket = 100;
     
    @Override
    public void run() {
        while (true) {
       // 调用方法 show(); } } // 同步监视器this private synchronized void show() { if (ticket > 0) { try { Thread.sleep(100); }catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + ":买票,票号为:" + ticket); ticket--; } } }

 

线程安全举例: 

   把厕所比作成共享数据(如以上的ticket),A进去上厕所了还没上完B就也进去上厕所了所以就出现了安全问题,

   解决方法就是在厕所上一把锁等A上完厕所之后B才能进去上厕所,即使A进入后睡了一觉(sleep)也要等A出来

   后B才能进入,从而解决了安全问题。  

标签:synchronized,Thread,参考,Windows,start,new,ticket,多线程,public
来源: https://www.cnblogs.com/lxh-daniel/p/16672220.html