Thread三种实现&多线程操作同一对象的互斥同步以及多对象的同步&定时器Timer

多线程

进程

  • 进程:(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。在进程是程序的基本执行实体,在当代面向线程设计的计算机结构中,进程是线程的容器,程是程序的实体。

  • 多线程:是指从软件或者硬件上实现多个线程并发执行的技术,是为了提高CPU等资源的使用率而采用的一种新技术。将一个执行活动-进程,拆分为多个小的执行片段,片段之间是共享数据而完成进程任务,进而提升整体处理性能。

  • Java程序运行

    • Java命令去启动JVM,JVM会启动一个进程,该进程会启动一个主线程。
    • JVM的启动是多线程的,因为它最低有两个线程启动了,主线程和垃圾回收线程。
  • 进程的实现方式:

    • 继承Thread类.

      /*for example*/
      public final String getName()	//获取线程的名称。
      public final void setName(String 	//name):设置线程的名称
      System.out.println(Thread.currentThread().getName());	//控制台显示当前指定对象名字。
      
      public class MyThread extends Thread {
      	public MyThread() {
      	}
      	
      	public MyThread(String name){
      		super(name);
      	}
      
      	@Override
      	public void run() {
      		for (int x = 0; x < 100; x++) {
      			System.out.println(getName() + ":" + x);
      		}
      	}
      }
      
      public static void main(String[] args) {
      		
      	/*method:the first...*/
      		MyThread myThread1 = new MyThread();
      		MyThread myThread2 = new MyThread();
      		
      		myThread1.setName("Tom");
      		myThread2.setName("Jack");
      		myThread1.start();
      		myThread2.start();
      		
      	/*method:the second...*/
      		 MyThread Thread1 = new MyThread("Tom");
      		 MyThread Thread2 = new MyThread("Jack");
      		 Thread1.start();
      		 Thread2.start();
      
    • 实现Runnable接口.

      public class MyRunnable implements Runnable {
      	@Override
      	public void run() {
      		for (int x = 0; x < 10; x++) {			
      			System.out.println(Thread.currentThread().getName() + ":" + x);
      		}
      	}
      
      }
      
      
      public class MyRunnable {
      	public static void main(String[] args) {	
      		MyRunnable my = new MyRunnable();
      
      	/*method:the first...*/		
      		Thread Thread1 = new Thread(my);
      		Thread Thread2 = new Thread(my);
      		Thread1.setName("Tom");
      		Thread2.setName("Jack");
      
      	/*method:the second...*/
      		Thread Thread1 = new Thread(my, "Tom");
      		Thread Thread2 = new Thread(my, "Jack");
      
      		Thread1.start();
      		Thread2.start();
      	}
      }
      
    • Callable&ExecutorService.

      /*for example*/		
      import java.util.concurrent.ExecutorService;
      import java.util.concurrent.Executors;		
      import java.util.concurrent.Callable;
      
      /*Callable:是带泛型的接口,这里指定的泛型其实是call()方法的返回值类型*/
      @SuppressWarnings("rawtypes")
      class MyCallable implements Callable {
      	/*Callable JDK1.5*/
      	@Override
      	public Object call() throws Exception {
      		for (int x = 0; x < 50; x++) {
      			System.out.println(Thread.currentThread().getName() + ":" + x);
      		}
      		return null;
      	}
      }
      
      public class CallableDemo {	
      	public static void main(String[] args) {
      		/*创建线程池对象*/
      		ExecutorService pool = Executors.newFixedThreadPool(2);
      
      		pool.submit(new MyCallable());
      		pool.submit(new MyCallable());
      	
      		pool.shutdown();
      	}
      }
      
      
  • 线程的调度和优先级问题

    • 线程的调度:分时调度,时间片轮转机制,而Java是采用抢占式调度。
    • 获取&设置线程优先级:Java中线程运行的优先级自高到底:10级->1级,默认5级;需要说明的是不是运行的级别越高就保证一定先执行该线程完该线程再执行其他低优先级的线程,只是保证其具有很大的可能有优先级。
  • 线程的控制

    • 休眠线程

      /*for example*/
      /*
      	public static void sleep(long millis)
       */
      import java.util.Date;
      
      public class ThreadSleep extends Thread {
      	@Override
      	public void run() {
      		for (int x = 0; x < 20; x++) {
      			System.out.println(getName() + ":" + x + ",Date:" + new Date());		
      			try {
      				Thread.sleep(1000);
      			} catch (InterruptedException e) {
      				e.printStackTrace();
      			}
      		}
      	}
      	
      	/* 解决直接重命名线程名称.*/
      	/*public ThreadSleep(String name){
      		super(name);
      	}*/
      }
      
      public class ThreadSleepDemo {
      	public static void main(String[] args) {
      		ThreadSleep Aa = new ThreadSleep();
      		ThreadSleep Bb = new ThreadSleep();
      		ThreadSleep Cc = new ThreadSleep();
      		
      		/*ThreadSleep Dd = new ThreadSleep("Smith");*/
      		Aa.setName("Tom");
      		Bb.setName("John");
      		Cc.setName("Jack");
      
      		Aa.start();
      		Bb.start();
      		Cc.start();
      	}
      }
      
    • 加入线程

      /*实现join功能*/
      package CompareTools;
      
      class sleepThread extends Thread {
      	@Override
      	public void run() {		
      		for (int i = 0; i < 10; ++i) {
      			try {
      				sleep(500);
      			} catch (InterruptedException e) {				
      				e.printStackTrace();
      			}
      			System.out.println(getName() + ":" + i);
      		}
      	}
      
      	public sleepThread() {
      	}
      
      	public sleepThread(String name) {
      		super(name);
      	}}
      
      public class TestFiles {
      	public static void main(String[] args) {
      		// TODO Auto-generated method stub
      		sleepThread spOne = new sleepThread("Tom");
      		sleepThread spTwo = new sleepThread("Jack");
      		sleepThread spThree = new sleepThread("Smith");	
      		spThree.start();
      		try {
      			spThree.join();
      		} catch (InterruptedException e) {
      			// TODO Auto-generated catch block
      			e.printStackTrace();
      		}		
      		spOne.start();
      		spTwo.start();		
      	}
      }
      /*Smith执行完成才继续执行后面的,但若将spThree放到try后面不会有描述的效果。*/
      
    • 礼让线程

      package CompareTools;
      
      class PriorityThread implements Runnable {
      	@Override
      	public void run() {
      		for (int i = 0; i < 10; ++i) {
      			
      			/* 实现Runnable无法使用Thread的getName函数. */			
      			System.out.println(Thread.currentThread().getName() + ":" + i);
      			
      			Thread.yield();	/*礼让不代表一定是程序严格运行一次就对方执行.*/
      		}
      	}
      }
      
      public class TestFiles {
      	public static void main(String[] args) {
      		PriorityThread pt = new PriorityThread();
      		PriorityThread ptt = new PriorityThread();
      
      		Thread trr = new Thread(pt, "Jack");
      		/*Thread trr = new Thread(pt, "Tom")一样运行看不出什么问题.*/
      		Thread tr = new Thread(ptt, "Tom");
      
      		tr.setName("newName");
      		trr.setName("newNameName");
      
      		tr.start();
      		trr.start();
      	}
      }
      
    • 守护线程

      /*public final void setDaemon(boolean on):将该线程标记为守护线程或用户线程。*/
      		当正在运行的线程都是守护线程时,Java 虚拟机退出。
      
      /*for example*/
      
      td1.setDaemon(true);
      td2.setDaemon(true);
      
      td1.start();
      td2.start();
      System.out.println("Over!");
      
      result:--循环结构写稍微大一些可以看到效果,循环到部分虚拟机就退出。
      Over!
      Thread-1:0
      Thread-0:0
      Thread-1:1
      Thread-0:1
      Thread-1:2
      Thread-0:2
      Thread-1:3
      Thread-1:4
      Thread-1:5
      Thread-1:6
      Thread-0:3
      Thread-1:7
      Thread-1:8
      Thread-0:4
      Thread-1:9
      Thread-1:10
      ...
      
    • 优先级设置

      package CompareTools;
      /*设置优先级不能保证一定是是优先级高的限制性,java中只能表示优先,但是不是先执行完高级别的再执行低级别.*/
      class PriorityThread implements Runnable {
      	@Override
      	public void run() {
      		for (int i = 0; i < 10; ++i) {
      			System.out.println(Thread.currentThread().getName() + ":" + i);
      			try {
      				Thread.sleep(100);
      			} catch (InterruptedException e) {
      				e.printStackTrace();
      			}
      		}
      	}
      }
      
      public class TestFiles {
      	public static void main(String[] args) {
      		PriorityThread pt = new PriorityThread();
      
      		Thread tr = new Thread(pt, "Jack");
      		Thread trr = new Thread(pt, "Tom");
      		Thread trrr = new Thread(pt, "Smith");
      
      		tr.setPriority(10);
      		trrr.setPriority(1);
      		tr.start();
      		trr.start();
      		trrr.start();
      
      	}
      }
      
    • 终止线程

      import java.util.Date;
      
      public class ThreadStop extends Thread {
      	@Override
      	public void run() {
      		System.out.println("开始执行:" + new Date());
      		/*睡眠10s*/		
      		try {
      			Thread.sleep(10000);
      		} catch (InterruptedException e) {			
      			System.out.println("线程被终止了!");
      		}
      		System.out.println("结束执行:" + new Date());
      	}
      }
      
      public class ThreadStopDemo {
      	public static void main(String[] args) {
      		ThreadStop ts = new ThreadStop();
      		ts.start();
      
      		/*3s不继续执行,中断.*/
      		try {
      			Thread.sleep(3000);
      			/*ts.stop();	直接终止.*/
      			ts.interrupt();		//线程被终止,结束执行还是可以显示.
      		} catch (InterruptedException e) {
      			e.printStackTrace();
      		}
      	}
      }
      
    • 加入并查看线程组

      public class ThreadGroupDemo {
      	public static void main(String[] args){
      		methodOne();		
      		methodTwo();
      	
      	}
      
      	private static void methodTwo() {
      		
      		ThreadGroup SetGroup = new ThreadGroup("NewGroupName");
      		MyRunnable SetThreadRunable = new MyRunnable();
      		
      		Thread t1 = new Thread(SetGroup, SetThreadRunable, "TheOne");
      		Thread t2 = new Thread(SetGroup, SetThreadRunable, "TheTwo");
      		
      		System.out.println(t1.getThreadGroup().getName());
      		System.out.println(t2.getThreadGroup().getName());		
      		
      		SetGroup.setDaemon(true);
      	}
      
      	private static void methodOne() {
      		MyRunnable SourceRunable = new MyRunnable();
      		Thread t1 = new Thread(SourceRunable, "FirstThread");
      		Thread t2 = new Thread(SourceRunable, "SecondThread");
      		
      		/*查看默认情况下,线程所属组别--默认是Main.*/
      	
      		ThreadGroup defaultTg1 = t1.getThreadGroup();
      		ThreadGroup defaultTg2 = t2.getThreadGroup();
      		
      		String nameOne = defaultTg1.getName();
      		String nameTwo = defaultTg2.getName();
      		System.out.println(nameOne);
      		System.out.println(nameTwo);
      		
      		System.out.println(Thread.currentThread().getThreadGroup().getName());
      	}
      }
      
  • 线程的生命周期
    新建->就绪->运行->阻塞->死亡。

  • 车站买票完整实现

    • 描述:买票用多线程实现,可以考虑适当的延迟,或者是为了保证程序的健壮性,保证问题不被掩盖掉。问题有这两种:一个是同一张车票卖了两次,二是车票卖到了负数。

    • 如图出错:异常

    • 为了数据的安全性需要添加锁进行实现而锁有两种:一种是Synchronized实现,一种是JDK1.4之后的lock实现。

      /*for example*/
      /*method:the first... */
      
      class SellTicket implements Runnable {	
      	private static int tickets = 100;	
      	private Object obj = new Object();
      	
      	@Override
      	public void run() {
      		while (true) {
      
      		/*在需要锁的地方添加锁对象,或者用obj替换SellTicket.class亦可!*/
      		/*this=SellTicket.class*/
      			synchronized (SellTicket.class) {
      				if (tickets > 0) {
      					try {
      						Thread.sleep(150);
      					} catch (InterruptedException e) {
      						e.printStackTrace();
      					}
      					System.out.println(Thread.currentThread().getName()
      							+ "printing" + (tickets--) + "th ticke!");
      }}}}}
      
      
      public class SellTicketDemo {
      	public static void main(String[] args) {
      		// 创建资源对象.
      		SellTicket st = new SellTicket();
      		
      		Thread thead1 = new Thread(st, "Windows-1:");
      		Thread thead2 = new Thread(st, "Windows-2:");
      		Thread thead3 = new Thread(st, "Windows-3:");
      		
      		thead1.start();
      		thead2.start();
      		thead3.start();
      	}
      }
      
      
      /*method:the second... */
      package CompareTools;
      
      import java.util.concurrent.locks.Lock;
      import java.util.concurrent.locks.ReentrantLock;
      
      class SellTicket implements Runnable {
      	private static int tickets = 100;
      	private Lock lock = new ReentrantLock();
      
      	@Override
      	public void run() {
      		while (true) {
      			try {
      				lock.lock();
      				if (tickets > 0) {
      					try {
      						Thread.sleep(100);
      					} catch (InterruptedException e) {
      						e.printStackTrace();
      					}
      					System.out.println(Thread.currentThread().getName()
      							+ "Printing" + (tickets--) + "th tickes!");
      				}
      			} finally {
      				lock.unlock();
      			}
      		}
      	}
      }
      
      public class TestFiles {
      	public static void main(String[] args) {
      		SellTicket sourceClass = new SellTicket();
      
      		Thread sta = new Thread(sourceClass, "Windows-1:");
      		Thread stb = new Thread(sourceClass, "Windows-2:");
      		Thread stc = new Thread(sourceClass, "Windows-3:");
      
      		sta.start();
      		stb.start();
      		stc.start();
      	}		
      }
      

关于使用继承Thread&lock

  • 未曾达到预期结果,出错代码在runable下运行正常,原因可能是实现接口的子类存在于Thread子类特有的差别,目前还无法明白具体原因,出错实例如下:

    /*for example--出错.*/
    --lock锁搭配try...finally...出错。
    package CompareTools;
    
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    class SellTicket extends Thread {
    	private static int tickets = 100;
    	private Lock lock = new ReentrantLock();
    
    	public SellTicket() {
    	}
    
    	public SellTicket(String name) {
    		super(name);
    	}
    
    	@Override
    	public void run() {
    		while (true) {	
    			try{
    				lock.lock();
    				if (tickets > 0) {
    					try {
    						Thread.sleep(100);
    					} catch (InterruptedException e) {
    						e.printStackTrace();
    					}
    					System.out.println(getName() + "Printing" + (tickets--)
    							+ "th tickes!");
    				}
    			}finally{
    				lock.unlock();}
    			}
    		}
    	}
    
    
    public class TestFiles {
    	public static void main(String[] args) {
    		SellTicket sta = new SellTicket("Windows-1:");
    		SellTicket stb = new SellTicket("Windows-2:");
    		SellTicket stc = new SellTicket("Windows-3:");
    
    		sta.start();
    		stb.start();
    		stc.start();
    	}
    
    }	
    
  • 多线程安全判定

    • 是否有多线程环境
    • 是否有共享数据
    • 是否有多条语句操作共享数据
  • 同步方法

    • 将方法有Synchronized修饰,可以同步方法。
    • Code eg:
      class SellTicket implements Runnable {
      
      	private static int tickets = 100;
      	private int x = 0;
      
      	@Override
      	public void run() {
      		while (true) {
      			if (x % 2 == 0) {
      				synchronized (SellTicket.class) {
      					if (tickets > 0) {
      						try {
      							Thread.sleep(100);
      						} catch (InterruptedException e) {
      							e.printStackTrace();
      						}
      						System.out.println(Thread.currentThread().getName()
      								+ "printing" + (tickets--) + "th ticket! ");
      					}
      				}
      			} else {
      				sellTicket();
      
      			}
      			x++;
      		}
      	}
      
      	private static synchronized void sellTicket() {
      		if (tickets > 0) {
      			try {
      				Thread.sleep(100);
      			} catch (InterruptedException e) {
      				e.printStackTrace();
      			}
      			System.out.println(Thread.currentThread().getName() + "printing"
      					+ (tickets--) + "th ticket! ");
      		}
      	}
      }
      
      public class SellTicketDemo {
      	public static void main(String[] args) {
      		SellTicket sourceClass = new SellTicket();
      
      		Thread window_1 = new Thread(sourceClass, "window_1:\t");
      		Thread window_2 = new Thread(sourceClass, "window_2:\t");
      		Thread window_3 = new Thread(sourceClass, "window_3:\t");
      
      		window_1.start();
      		window_2.start();
      		window_3.start();
      	}
      }
      
  • 同步的使用可以修改为对:要求线程严格遵守一个线程执行一次的要求,也可以利用经典的互斥问题,哲学家就餐问题和生产消费问题。

互斥&同步实现

  • 描述:问题的起源。

  • 首先是由于线程的不严格控制导致的生产消费的死锁问题,也就是多个对象占有其他对象所必需的资源,导致自己无法获取资源,陷入无限等待的姿态。

    • 互斥条件:指进程对所分配到的资源进行排它性使用,即在一段时间内某资源只由一个进程占用。如果此时还有其它进程请求资源,则请求者只能等待,直至占有资源的进程用毕释放。

    • 请求和保持条件:指进程已经保持至少一个资源,但又提出了新的资源请求,而该资源已被其它进程占有,此时请求进程阻塞,但又对自己已获得的其它资源保持不放。

    • 不剥夺条件:指进程已获得的资源,在未使用完之前,不能被剥夺,只能在使用完时由自己释放。

    • 环路等待条件:指在发生死锁时,必然存在一个进程——资源的环形链,即进程集合{P0,P1,P2,···,Pn}中的P0正在等待一个P1占用的资源;P1正在等待P2占用的资源,……,Pn正在等待已被P0占用的资源。

  • 解除死锁状态

    • 死锁预防:这是一种较简单和直观的事先预防的方法。方法是通过设置某些限制条件,去破坏产生死锁的四个必要条件中的一个或者几个,来预防发生死锁。预防死锁是一种较易实现的方法,已被广泛使用。但是由于所施加的限制条件往往太严格,可能会导致系统资源利用率和系统吞吐量降低。

    • 死锁避免:系统对进程发出的每一个系统能够满足的资源申请进行动态检查,并根据检查结果决定是否分配资源;如果分配后系统可能发生死锁,则不予分配,否则予以分配。这是一种保证系统不进入死锁状态的动态策略。

    • 死锁检测和解除:先检测,这种方法并不须事先采取任何限制性措施,也不必检查系统是否已经进入不安全区,此方法允许系统在运行过程中发生死锁。但可通过系统所设置的检测机构,及时地检测出死锁的发生,并精确地确定与死锁有关的进程和资源。检测方法包括定时检测、效率低时检测、进程等待时检测等。

    • Code 同步互斥:

      /*
      Object类中提供的三个方法:
      	wait():等待
      	notify():唤醒单个线程
      	notifyAll():唤醒所有线程
      	为什么不定义在Thread类中?
      			这些方法的调用必须通过锁对象Lock调用,而我们使用的锁对象可能是任意锁对象.
      		所以,这些方法必须定义在Object类中是为了实现对象的通用性。
      */
      
      /* Tom-5.
       * Jack-6. 
       */
      
      /*该部分代码块实现的是:多线程情况下,保证线程运行一步就暂停,而然另外线程运行*/
      package CompareTools;
      class Student {
      	String name;
      	int age;
      	boolean flag;
      }
      class GetThread implements Runnable {
      	private Student s;
      	public GetThread(Student s) {
      		this.s = s;
      	}
      	@Override
      	public void run() {
      		while (true) {
      			synchronized (s) {	/*锁定局部,而实际造成的结果是完全锁定执行,防止干扰*/
      				if(!s.flag){	/*为true则获取值,显示在界面*/
      					try {
      						s.wait();	/*解锁+等待...*/
      					} catch (InterruptedException e) {
      						e.printStackTrace();
      					}
      				}				
      				System.out.println(s.name + "---" + s.age);					
      				s.flag = false;		/*使用完成后就修改,保证SetThread运行.*/	
      				s.notify();	/*唤醒GetThread=唤醒...*/
      }}}}
      
      class SetThread implements Runnable {
      	private Student s;
      	private int x = 0;
      	public SetThread(Student s) {
      		this.s = s;
      	}
      	@Override
      	public void run() {
      		while (true) {
      			synchronized (s) {	/*锁定局部,而实际造成的结果是完全锁定执行,防止干扰*/
      				if(s.flag){		/*为flase执行赋值操作...*/
      					try {
      						s.wait(); 	/*解锁+等待...*/
      					} catch (InterruptedException e) {
      						e.printStackTrace();
      					}
      				}				
      				if (x % 2 == 0) {
      					s.name = "Five";
      					s.age = 5;
      				} else {
      					s.name = "Six";
      					s.age = 6;
      				}
      				x++; 			
      				s.flag = true;	/*使用完成后就修改,保证GetThread运行.*/	
      				s.notify(); 	/*唤醒GetThread=唤醒..*/
      }}}}
      public class TestFiles {
      	public static void main(String[] args) {	
      		Student s = new Student();		
      	
      		SetThread st = new SetThread(s);
      		GetThread gt = new GetThread(s);
      		
      		Thread t1 = new Thread(st);
      		Thread t2 = new Thread(gt);
      		
      		t1.start();
      		t2.start();
      	}
      }
      
  • 经典的互斥同步-生产消费问题

描述:假设消费者生产者使用一个容器,生产者将产品生产到容器中,消费者将容器中的产品拿出来消费。

程序进入后需要首先检测信号量,判断是否容器存在产品,若不存在,生产者互斥占有并且生产产品放至容器,然后退出互斥占有状态,关闭锁。保证消费者可以获取容器并且使用,消费者使用使用时设置互斥锁锁定使用,使用完成返回容器,放开互斥锁。并设置信号量,保证自己不占有为空的容器,导致死锁。

  • Code - 互斥同步

    /*for example*/
    
    上代码结构:
    	
    	- 设置对象简单具体类,是为了使用共享boolean变量,和设置/获取方法。
    	- 设置互斥设置名字 <=> 生产者互斥同步生产产品.
    	- 设置互斥获取名字 <=> 消费者互斥同步消费产品.
    	- 主函数,调用两个线程:互斥设置&互斥共享线程。
    
    	- 创建两个对象,进行类似生产消费操作code。	
    package CompareTools;
    
    class Student {
    	String name;
    	int age;
    	boolean flag;
    }
    
    class GetThread implements Runnable {
    	private Student s;
    
    	public GetThread(Student s) {
    		this.s = s;
    	}
    
    	@Override
    	public void run() {
    		while (true) {
    			synchronized (s) { /* 锁定局部,而实际造成的结果是完全锁定执行,防止干扰 */
    				if (!s.flag) { /* 为true则获取值,显示在界面 */
    					try {
    						s.wait(); /* 解锁+等待... */
    					} catch (InterruptedException e) {
    						e.printStackTrace();
    					}
    				}
    				System.out.println(Thread.currentThread().getName()+ s.name + "---" + s.age);
    				s.flag = false; /* 使用完成后就修改,保证SetThread运行. */
    				s.notify(); /* 唤醒GetThread=唤醒... */
    			}
    		}
    	}
    }
    
    class SetThread implements Runnable {
    	private Student s;
    	private int x = 0;
    
    	public SetThread(Student s) {
    		this.s = s;
    	}
    
    	@Override
    	public void run() {
    		while (true) {
    			synchronized (s) { /* 锁定局部,而实际造成的结果是完全锁定执行,防止干扰 */
    				if (s.flag) { /* 为flase执行赋值操作... */
    					try {
    						s.wait(); /* 解锁+等待... */
    					} catch (InterruptedException e) {
    						e.printStackTrace();
    					}
    				}
    				if (x % 2 == 0) {
    					s.name = "Five";
    					s.age = 5;
    				} else {
    					s.name = "Six";
    					s.age = 6;
    				}
    				System.out.println(Thread.currentThread().getName());
    				x++;
    				s.flag = true; /* 使用完成后就修改,保证GetThread运行. */
    				s.notify(); /* 唤醒GetThread=唤醒.. */
    			}
    		}
    	}
    }
    
    public class TestFiles {
    	public static void main(String[] args) {
    		Student s = new Student();
    
    		SetThread st = new SetThread(s);
    		GetThread gt = new GetThread(s);
    
    		Thread t1 = new Thread(st, "st");
    		Thread t2 = new Thread(gt, "gt");
    
    		t1.start();
    		t2.start();
    
    		System.out.println("------this is a dividing line------");
    
    		Student ss = new Student();
    
    		SetThread stt = new SetThread(ss);
    
    		GetThread gtt = new GetThread(ss);
    
    		Thread t11 = new Thread(stt, "stt");
    		Thread t22 = new Thread(gtt, "gtt");
    
    		t11.start();
    		t22.start();
    
    	}
    }
    
  • 运行结果:

  • 运行结果一:resultOne

  • 运行结果二:resultTwo

  • 改进的生产者消费者Code

    /*for example*/
    /*Tips:添加生产消费过程,方面查看逻辑,同时存在第二次运行可能存在3比2先走,只需要清理控制台,等几秒钟再执行即可,因为Java没有指针不能操作内存,而自动回收机制效率不高。*/
    
    package CompareTools;
    
    class Student {
    	String name = "Products";
    	/*flag判断的是容器是否存在商品,存在true;不存在false.*/
    	boolean flag = false;
    }
    
    class GetThread implements Runnable {
    	private Student s;
    
    	public GetThread(Student s) {
    		this.s = s;
    	}
    
    	@Override
    	public void run() {
    		while (true) {
    			if (s.flag) { /*有成品則消費.*/
    				synchronized (s) { /* 锁定局部互斥消费,防止干扰 */
    					System.out.println(Thread.currentThread().getName()+"expensing "+
    							s.name);
    					s.flag = false; /* 使用完成后就修改,保证生产者运行. */
    					s.notify(); /* 唤醒GetThread=唤醒... */
    				}
    
    			}
    		}
    	}
    }
    
    class SetThread implements Runnable {
    	private Student s;
    	private int x = 0;
    
    	public SetThread(Student s) {
    		this.s = s;
    	}
    
    	@Override
    	public void run() {
    		while (true) {
    			if (!s.flag) { /*没有产品则生产产品。*/
    				synchronized (s) { /* 锁定局部互斥生产,防止干扰 */
    					if (x % 2 == 0) {
    						s.name = "CellPhone-2";						
    					} else {
    						s.name = "Pad-3";
    					
    					}
    					System.out.println(Thread.currentThread().getName()+"Producting: "
    							+ s.name );// result:two
    					x++;
    					s.flag = true; /* 使用完成后就修改,保证消费者运行. */
    					s.notify(); /* 唤醒GetThread=唤醒...*/
    				}
    
    			}
    		}
    	}
    }
    
    public class TestFiles {
    	public static void main(String[] args) {
    		Student s = new Student();
    
    		SetThread st = new SetThread(s);
    		GetThread gt = new GetThread(s);
    
    		Thread t1 = new Thread(st, "ThreadOneSet: ");
    		Thread t2 = new Thread(gt, "ThreadOneGet: ");
    
    		t1.start();
    		t2.start();
    
    		System.out.println("------this is a dividing line------");
    
    		Student ss = new Student();
    
    		SetThread stt = new SetThread(ss);
    
    		GetThread gtt = new GetThread(ss);
    
    		Thread t11 = new Thread(stt, "ThreadTwoSet: ");
    		Thread t22 = new Thread(gtt, "ThreadTwoGet: ");
    
    		t11.start();
    		t22.start();
    
    	}
    }
    
    
  • 线程池

    • 线程池,工具类,所有函数均由static修饰。

    • 常用函数Code如下:

      import java.util.concurrent.ExecutorService;
      import java.util.concurrent.Executors;
      
      class MyRunnable implements Runnable{
      	public void run() {
      		for (int x = 0; x < 100; x++) {
      			System.out.println(Thread.currentThread().getName() + ":" + x);
      		}}
      }
      
      public class ExecutorsDemo {
      	public static void main(String[] args) {
      		// 创建一个线程池对象,参数为线程个数。
      		// public static ExecutorService newFixedThreadPool(int nThreads)
      		ExecutorService pool = Executors.newFixedThreadPool(2);
      
      		// 可以执行Runnable对象或者Callable对象的线程.
      		pool.submit(new MyRunnable());
      		pool.submit(new MyRunnable());
      
      		/*结束线程池,否则不会死亡,等待下一对象来说使用.*/
      		pool.shutdown();
      	}
      }
      
  • Callable&executors

    • Code eg:
      import java.util.concurrent.ExecutorService;
      import java.util.concurrent.Executors;		
      import java.util.concurrent.Callable;
      
      /*Callable:是带泛型的接口,这里指定的泛型其实是call()方法的返回值类型*/
      @SuppressWarnings("rawtypes")
      class MyCallable implements Callable {
      	/*Callable JDK1.5*/
      	@Override
      	public Object call() throws Exception {
      		for (int x = 0; x < 50; x++) {
      			System.out.println(Thread.currentThread().getName() + ":" + x);
      		}
      		return null;
      	}
      }
      
      public class CallableDemo {	
      	public static void main(String[] args) {
      		/*创建线程池对象*/
      		ExecutorService pool = Executors.newFixedThreadPool(2);
      
      		pool.submit(new MyCallable());
      		pool.submit(new MyCallable());
      	
      		pool.shutdown();
      	}
      }
      
  • Callable&executors->sum.

    • Code eg:sum.
      import java.util.concurrent.Callable;
      import java.util.concurrent.ExecutionException;
      import java.util.concurrent.ExecutorService;
      import java.util.concurrent.Executors;
      import java.util.concurrent.Future;
      
      /*
       * Sum.
       */
      class MyCallable implements Callable<Integer> {
      
      	private int number;
      
      	public MyCallable(int number) {
      		this.number = number;
      	}
      
      	@Override
      	public Integer call() throws Exception {
      		int sum = 0;
      		for (int x = 1; x <= number; x++) {
      			sum += x;
      		}
      		return sum;
      	}
      }
      
      public class CallableDemo {
      	public static void main(String[] args) throws InterruptedException,
      			ExecutionException {
      
      		ExecutorService pool = Executors.newFixedThreadPool(2);
      
      		Future<Integer> result_01 = pool.submit(new MyCallable(50));
      		Future<Integer> result_02 = pool.submit(new MyCallable(100));
      
      		Integer sumOne = result_01.get();
      		Integer sumTwo = result_02.get();
      
      		System.out.println("Sum<50>: " + sumOne);
      		System.out.println("Sum<100>: " + sumTwo);
      
      		/* 结束线程池. */
      		pool.shutdown();
      	}
      }	
      
  • 匿名内部类&线程的使用

    • 匿名内部本质上是需要一个接口的实现类或者是抽象类的子类对象,实现润able的内部类有如下几种实现方法。
    • Code eg:
      /*for example*/
      
      /*
       * 匿名内部类的格式:
       * 		new 类名或者接口名() {
       * 			重写方法;
       * 		};
       * 		本质:是该类或者接口的子类对象。
       */
      public class ThreadInner {
      	public static void main(String[] args) {
      		/*继承Thread类来实现多线程*/
      		/*new Thread(){override Code block}.start();*/
      		new Thread() {
      			public void run() {
      				for (int x = 0; x < 100; x++) {
      					System.out.println(Thread.currentThread().getName() + ":"
      							+ x);
      				}
      			}
      		}.start();
      
      		/*实现Runnable接口来实现多线程*/
      		/*new Thread(override Code block){}.start();*/
      		new Thread(new Runnable() {
      			@Override
      			public void run() {
      				for (int x = 0; x < 100; x++) {
      					System.out.println(Thread.currentThread().getName() + ":"
      							+ x);
      				}
      			}
      		}) {
      		}.start();
      
      		/*更有难度的嵌套,本质上考验到底执行哪一部分.*/
      		/*new Thread(new Runable()代码块){抽象方法Runable代码块}.start();-按照逻辑顺序,走子类对象部分,也就是new Thread(){override Code block}.start();*/
      		new Thread(new Runnable() {
      			@Override
      			public void run() {
      				for (int x = 0; x < 100; x++) {
      					System.out.println("hello" + ":" + x);
      				}
      			}
      		}) {
      			public void run() {
      				for (int x = 0; x < 100; x++) {
      					System.out.println("world" + ":" + x);
      				}
      			}
      		}.start();
      	}
      }
      
  • Timer定时器

    • 提供一个类Timer实现定时执行操作的功能。
    • Code eg:文件夹删除.
      import java.io.File;
      import java.text.ParseException;
      import java.text.SimpleDateFormat;
      import java.util.Date;
      import java.util.Timer;
      import java.util.TimerTask;
      
      class DeleteFolder extends TimerTask {
      
      	@Override
      	public void run() {
      		File srcFolder = new File("其他文件");
      		deleteFolder(srcFolder);
      	}
      
      	/*递归删除目录*/
      	public void deleteFolder(File srcFolder) {
      		File[] fileArray = srcFolder.listFiles();
      		if (fileArray != null) {
      			for (File file : fileArray) {
      				if (file.isDirectory()) {
      					deleteFolder(file);
      				} else {
      					System.out.println(file.getName() + ":" + file.delete());
      				}
      			}
      			System.out.println(srcFolder.getName() + ":" + srcFolder.delete());
      		}
      	}
      }
      
      public class TimerTest {
      	public static void main(String[] args) throws ParseException {
      		Timer t = new Timer();
      
      		String s = "10:05 2018/11/11"; 
      		SimpleDateFormat sdf = new SimpleDateFormat("HH:mm yyyy/MM/dd");
      		Date d = sdf.parse(s);
      
      		t.schedule(new DeleteFolder(), d);
      	}
      }
      

猜你喜欢

转载自blog.csdn.net/CS_GaoMing/article/details/83956405