码迷,mamicode.com
首页 > 编程语言 > 详细

多线程售票模型

时间:2017-06-27 23:36:07      阅读:262      评论:0      收藏:0      [点我收藏+]

标签:cat   注意   ++   static   nts   i++   mini   衣服   线程   

上次Java实验课就写了一次,但是比较简单,这里再好好写一下

这里用集合类LinkList来存储车票

注意线程是抢占式时的,虽然在出票的时候是一个个出的,但是在Sysout.out.println()的时候被其他线程抢占,所以输出可能不是顺序的,这里用sleep方法之后就顺序输出了,为什么?

一般不用加sleep,因为后台出票的时候确实是一个个按照顺序出的。只是在打印的时候抢占了。

package com.ticket.thread;

import java.util.LinkedList;

import com.sun.org.apache.xalan.internal.xsltc.compiler.sym;

/**
 * 带销售的车票
 * 
 * @author hwyou
 *
 */
public class Ticket {
    
    // 所有的车票(容器)
    LinkedList<Integer> list = new LinkedList<>();
    
    /**
     * 
     * @param size
     *            车票的数量
     */
    public Ticket(int size) {
        for(int i = 1; i <= size; i ++) {
            list.add(i);
        }
        System.out.println(list);
    }
    
    //同步关键字,其他线程在当前线程没有结束之前是不能访问的
    //"试衣间",对当前衣服在试衣间试衣服的时候其他人不能访问
    public  int sell() throws NoTicketException {
//        int t = list.getFirst();
        
        //异常,对正常流程的中断
        if(list.size()==0) {
            throw new NoTicketException();
        }
        
        synchronized(list) {
            int t = list.removeFirst();    
            
        
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return t;
        }
        
    }
    
    public void show() {
        System.out.println("剩余" + list);
    }

    
}

 

这里加synchronized关键字,同步化之后,避免了多个线程访问同一张票,上个写法没有很体现出来,我们这样写,再用sleep放大,就提现了synchronized重要了。

有问题的写法:

package com.ticket.thread;

import java.util.LinkedList;

import com.sun.org.apache.xalan.internal.xsltc.compiler.sym;

/**
 * 带销售的车票
 * 
 * @author hwyou
 *
 */
public class Ticket {
    
    // 所有的车票(容器)
    LinkedList<Integer> list = new LinkedList<>();
    
    /**
     * 
     * @param size
     *            车票的数量
     */
    public Ticket(int size) {
        for(int i = 1; i <= size; i ++) {
            list.add(i);
        }
        System.out.println(list);
    }
    
    // 同步关键字,其他线程在当前线程没有结束之前是不能访问的
    // "试衣间",对当前衣服在试衣间试衣服的时候其他人不能访问
    public int sell() throws NoTicketException {
        int t = list.getFirst();

        // 异常,对正常流程的中断
        if (list.size() == 0) {
            throw new NoTicketException();
        }

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        list.removeFirst();

        return t;

    }
    
    public void show() {
        System.out.println("剩余" + list);
    }

    
}

因为在实际项目中,取票和出票中间确实可能有其他代码,其他操作,没有同步,就可能出这种错误

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
pool-1-thread-1开放
pool-1-thread-2开放
pool-1-thread-3开放
pool-1-thread-4开放
pool-1-thread-5开放
pool-1-thread-1售出1
pool-1-thread-4售出1
pool-1-thread-2售出1
pool-1-thread-3售出1
pool-1-thread-5售出1
pool-1-thread-3售出4
pool-1-thread-1售出4
pool-1-thread-4售出4
pool-1-thread-2售出4
pool-1-thread-5售出4
pool-1-thread-1售出6
pool-1-thread-2售出6
pool-1-thread-3售出6
pool-1-thread-4售出6
pool-1-thread-5售出7
pool-1-thread-3售出10
pool-1-thread-2售出10
pool-1-thread-4售出10
pool-1-thread-1售出10
pool-1-thread-5售出11
pool-1-thread-1售出14
pool-1-thread-3售出14
pool-1-thread-2售出14
pool-1-thread-4售出14
pool-1-thread-5售出15
pool-1-thread-5售罄
pool-1-thread-4售出19
pool-1-thread-1售罄
pool-1-thread-3售罄
pool-1-thread-2售罄
pool-1-thread-4售罄

一些票因为线程访问同一张票也减减,所以直接在后台就没了,前端打印自然也没有显示

 

非线程池写法:

package com.ticket.thread;
/**
 * 自定义一个线程(售票窗口)
 * @author Administrator
 *
 */
public class TicketOffice extends Thread {
    /**
     * 要销售的车票(引用)
     */
    Ticket ticket;
    
    /**
     * 创建(初始化)售票窗口
     * @param ticket
     *             待销售的车票
     * @param name
     *             窗口名称
     */
    public TicketOffice(Ticket ticket, String name) {
        this.ticket = ticket;
        setName(name);
    }
    
    @Override
    public void run() {
        // TODO Auto-generated method stub
        super.run();
        
        //售票
        System.out.println(getName()+ "开放");
        while (true) {
            try {
                int t = ticket.sell();
                System.out.println(getName() + "售出:" + t);
            } catch (NoTicketException e) {
                // TODO Auto-generated catch block
//                e.printStackTrace();
                System.out.println(getName()+"售罄");
                break;
            }
        }
        System.out.println("关闭");
    }
}

 

线程池写法:

package com.ticket.thread;

public class SaleTask implements Runnable{
    Ticket ticket;
    
    public SaleTask(Ticket ticket) {
        this.ticket = ticket;
    }
    
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"开放");
        while(true) {
            try {
                int t = ticket.sell();
                System.out.println(Thread.currentThread().getName() + "售出" + t);
            } catch (Exception e) {
                System.out.println(Thread.currentThread().getName() +"售罄");
                break;
            }
        }
    }
    
}

 

自定义异常类:

package com.ticket.thread;
/**
 * 消息对象(信号)
 * @author Administrator
 *
 */
public class NoTicketException extends Exception{
        
}

 

入口:

package com.ticket.thread;

import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class App {
    public static void main(String[] args) {
        //车票
        Ticket ticket = new Ticket(20);
        
//        //创建窗口
//        TicketOffice office1 = new TicketOffice(ticket, "窗口一");
//        TicketOffice office2 = new TicketOffice(ticket, "窗口二");
//        TicketOffice office3 = new TicketOffice(ticket, "窗口三");
        //ExecutorService是一个对象,容器,装线程的池子
        ExecutorService pool = Executors.newFixedThreadPool(5);
        
        for(int i = 0; i < 5; i++) {
            pool.execute(new SaleTask(ticket));
        }
        
        pool.shutdown();
//        office1.start();
//        office2.start();
//        office3.start();
    }
}

 

多线程售票模型

标签:cat   注意   ++   static   nts   i++   mini   衣服   线程   

原文地址:http://www.cnblogs.com/zhangmingzhao/p/7087425.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!