1.多线程的概述和多线程的创建方法
package Thread; /* * 多线程 * 进程:当前正在运行的程序,一个应用程序在内存中的执行区域 * 线程:是进程中的执行控制单元,执行路径 * 单线程:安全性高,效率低 * 多线程:安全性低,效率高 * * * 多线程的实现方式: * Thread * 创建线程的方法: * 一种方法是将类声明为 Thread 的子类。 * 该子类应重写 Thread 类的 run 方法。接下来可以分配并启动该子类的实例。 * String getName()获取线程名称 * void setname(String name) 改变线程名称 * 线程的顺序不定,因为CPU执行程序的随机性, * * * 另一种方法是声明实现 Runnable 接口的类。该类然后实现 run 方法。 * 然后可以分配该类的实例,在创建 Thread 时作为一个参数来传递并启动。 * */ class MyThread extends Thread{ @Override public void run() { for (int i = 0; i < 20; i++) { System.out.println(getName()+":"+i); } } } class Thread2 implements Runnable{ @Override public void run() { // TODO Auto-generated method stub // currentThread放回当前所正在执行的线程对象的引用 直接类名调用 所以是static修饰符修饰 for (int i = 0; i < 20; i++) { System.out.println(Thread.currentThread().getName()+i); } } } public class Threadtest { public static void main(String[] args) { // method1(); // method2(); } public static void method2() { Thread2 th2=new Thread2(); Thread t=new Thread(th2); // 启动线程 t.setName("第二种方法创建线程启动。。。。。。"); t.start(); } public static void method1() { // 创建线程实例 MyThread mt=new MyThread(); // 启动线程 mt.setName("一号线程"); mt.start(); // start会调用run方法 // 创建线程实例 MyThread mt1=new MyThread(); // 启动线程 mt1.setName("二号线程"); mt1.start(); // start会调用run方法 } }
2.案例---模拟火车站售票
package ThreadTest; /*模拟火车售票 * 分析: * 火车票总数 每售出一张数量减一 0张停止出售 * 总数小于1停止售票 * 多个售票窗口 使用多线程 模拟多个窗口进行售票 * * * sleep方法:让当前线程休息 时间 s * * * * */ public class tickettest { public static void main(String[] args) throws InterruptedException { // 创建线程对象 // runable的实现对象 ticketThread tt=new ticketThread(); Thread t1=new Thread(tt); t1.setName("一号窗口售票"); Thread t2=new Thread(tt); t2.setName("二号窗口售票"); Thread t3=new Thread(tt); t3.setName("三号窗口售票"); t1.start(); t2.start(); t3.start(); } }
package ThreadTest; public class ticketThread implements Runnable{ int ticket=100;//火车票总数 Object obj=new Object(); @Override public void run() { // TODO Auto-generated method stub /* 出售火车票: * 如果有一张票 * t1,t2,t3 * t1 t2都购买 * ticket=0 * ticket=-1 * */ boolean flag=true; while(flag) { synchronized (obj) { if (ticket>0) { try { Thread.sleep(100); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+":"+ticket--); }else { flag=false; } } } } } /*出现的问题:出现售票重复或者售票为负 * 一号窗口售票:5 * 三号窗口售票:4 * 一号窗口售票:3 * 二号窗口售票:2 * 三号窗口售票:1 * 一号窗口售票:0 * 二号窗口售票:-1 *原因: * 多线程操作同一数据 * 使用同步代码解决多线程案例中出现的问题 *解决方案: * synchronized 同步 修饰代码块和方法 被修饰的代码块和方法一旦某个线程访问 则直接锁住 其他线程无法访问 * 同步代码(被锁对象){ * } * 锁对象需要被多线程访问 * * */