深入浅出java多线程

 

一.多线程的第一种实现方式

    继承Thread类

public class MyThread extends Thread {

	public void run() {
		for(int i=0;i<67;i++) {
			System.out.println(getName()+" "+i);
		}
	}
}

 

二.多线程的第二种实现方式

实现Runnable接口

public class MyRunnable implements Runnable {

	@Override
	public void run() {
		for(int i=0;i<67;i++) {
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName()+" "+i);
		}
		//用Tread类来获取当前线程对象比较简单,直接用this就可以
		//用Runnable接口就需要使用Tread.currentThread()
		
		//继承方式,直接创建Thread子类对象
		//实现Runnable接口创建的对象只能作为线程对象的target

	}

}

 

三.Tread类中的一些常用方法

1.public final void join():等待该线程终止
 为什么要用join()方法
 在很多情况下,主线程生成并起动了子线程,如果子线程里要进行大量的耗时的运算,
 主线程往往将于子线程之前结束,但是如果主线程处理完其他的事务后,需要用到子线程的处理结果,
 也就是主线程需要等待子线程执行完成之后再结束,这个时候就要用到join()方法了。
 

public static void main(String[]args) {
		Threadjoin m1=new Threadjoin();
		Threadjoin m2=new Threadjoin();
		m1.start();
		try {
			m1.join();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		m2.start();
		
	}
public void run() {
		for(int i=0;i<67;i++) {
			try {
				Thread.sleep(1);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println(getName()+" "+i);
		}
	}

 

2.yield

sleep()和yield()的区别
     (1)sleep()使当前线程进入停滞状态,所以执行sleep()的线程在指定的时间内肯定不会被执行;
      yield()只是使当前线程重新回到可执行状态,所以执行yield()的线程有可能在进入到
       可执行状态后马上又被执行。
     (2)sleep 方法使当前运行中的线程睡眼一段时间,进入不可运行状态,这段时间的长短是
     由程序设定的,yield 方法使当前线程让出 CPU 占有权,但让出的时间是不可设定的。
     实际上,yield()方法对应了如下操作:先检测当前是否有相同优先级的线程处于同可运行状态,
     如有,则把 CPU  的占有权交给此线程,否则,继续运行原来的线程。
     所以yield()方法称为“退让”,它把运行机会让给了同等优先级的其他线程
   (3)sleep 方法允许较低优先级的线程获得运行机会,但 yield()  方法执行时,
   当前线程仍处在可运行状态,所以,不可能让出较低优先级的线程些时获得 CPU 占有权。
   在一个运行系统中,如果较高优先级的线程没有调用 sleep 方法,又没有受到 I\O 阻塞,
   那么,较低优先级线程只能等待所有较高优先级的线程运行结束,才有机会运行。
 

public void run() {
		for(int i=1;i<88;i++) {
			System.out.println(getName()+" "+i);
		}
		Thread.yield();
	}

 

3.Deaaemon

public final void setDaemon(boolean on) :true时,表示为守护线程
  将该线程标记为守护线程或用户线程。当正在运行的线程都是守护线程时,Java 虚拟机退出。
 守护线程不会立即结束掉,它会执行一段时间在结束掉)

该方法必须在启动线程前调用。

	public static void main(String[]args) {
		 TreadDaemon t1=new  TreadDaemon();
		 TreadDaemon t2=new  TreadDaemon();
		 t1.setDaemon(true);
		 t2.setDaemon(true);
		 t1.start();
		 t2.start();
		 
		 Thread.currentThread().setName("刘备");
			for(int x =0 ; x < 5 ; x ++) {
				System.out.println(Thread.currentThread().getName()+":"+x);
			}
	}

 

三.模拟电影院卖票模式

1.

/**
 * 模拟电影院卖票
 * 实现多线程 方式一
 * */
public class test {

	public static void main(String[]args) {
		ticket t1=new ticket();
		ticket t2=new ticket();
		ticket t3=new ticket();
		//给各个线程起名字
		t1.setName("窗口1");
		t2.setName("窗口2");
		t3.setName("窗口3");
		//启动线程
		t1.start();
		t2.start();
		t3.start();
		
	}
}
public class ticket extends Thread{

	private static int ticket=100;
	public void run() {
		while(true) {
			if(ticket>0) {
				System.out.println(getName()+"正在售出第"+(ticket--)+"张票");
			}else {
				System.exit(0);
			}
		}
	}
}


2.

/**
 * 模拟电影院卖票
 * 实现多线程  方式二
 * */
public class test {

	public static void main(String[]args) {
		seilTicket s=new seilTicket();
		
		Thread t1=new Thread(s,"窗口1");
		Thread t2=new Thread(s,"窗口2");
		Thread t3=new Thread(s,"窗口3");
		//启动线程
		t1.start();
		t2.start();
		t3.start();
	}
}

 

public class seilTicket implements Runnable {

	private static int tickets=100;
	@Override
	public void run() {
		
		while(true) {
			if(tickets>0) {
				System.out.println(Thread.currentThread().getName()+"正在售出第"
						+(tickets--)+"张票");
			}else {
				System.exit(0);
			}
		}

	}

}

 


3. 模拟电影院卖票
 加入睡眠,更符合实际情况,卖票系统会有延时
  如果没有加入同步代码块,则会引起卖出负票,零票,以及一张票被卖出多次
     这是由于CPU的执行有一个特点(具有原子性操作:最简单最基本的操作)
      t1线程进来,睡完了,100张票
      原子性操作:记录以前的值
      接着tickets-- :票变成99张票
     在马上输出99张票之前,t2/t3进来,直接输出记录的以前那个tickets的值
      出现:
       窗口1正在出售第100张票
       窗口3正在出售第99张票
       窗口2正在出售第99张票
      
      原子性操作
      
  
 引入同步代码块synchronized

 

	public static void main(String[]args) {
		seil s=new seil();
		
		Thread t1=new Thread(s,"窗口1");
		Thread t2=new Thread(s,"窗口2");
		Thread t3=new Thread(s,"窗口3");
		
		t1.start();
		t2.start();
		t3.start();
	}
public class seil implements Runnable {

	private static int tickets=100;
	//同一个锁对象
	private Object o=new Object();
	@Override
	public void run() {
		while(true) {
			//同步代码块
			synchronized(o){//这就相当于一个线程执行到该对象的synchronized方法时,
							//就为这个对象加上了一把锁,锁住了这个对象,
							//别的线程在调用该方法时,发现了这把锁以后就继续等待下去了。
				if(tickets>0) {
					try {
						Thread.sleep(10);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					
					System.out.println(Thread.currentThread().getName()
							+"正在售出第"+(tickets--)+"张票");
				}else {
					System.exit(0);
				}
			}
		}

	}

}

synchronized关键字是一个修饰符,可以修饰方法或代码块,其的作用就是,对于同一个对象
   (不是一个类的不同对象), 当多个线程都同时调用该方法或代码块时,必须依次执行,也就是说,
   如果两个或两个以上的线程同时执行该段代码时,如果一个线程已经开始执行该段代码,
  则另 外一个线程必须等待这个线程执行完这段代码才能开始执行。

 

 

 

 

 

 

4.静态同步方法

 

public class seil implements Runnable {

	private static int tickets=100;
	private Object o=new Object();
	int x=0;
	@Override
	public void run() {
		while(true) {
			if(x%2==0) {
				synchronized(seilTicket.class) {
					if(tickets>0) {
						try {
							Thread.sleep(100);
						} catch (InterruptedException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
						System.out.println(Thread.currentThread().getName()
								+"正在售出第"+(tickets--)+"张票");
					}else {
						System.exit(0);
					}
				}
			}else {
				seilTickets();
			}
			x++;
		}

	}
	//静态同步方法
	public synchronized static void seilTickets() {
		if(tickets>0) {
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName()
					+"正在售出第"+(tickets--)+"张票");
		}else {
			System.exit(0);
		}
	}

}

 

四.lock

 

public static void main(String[]args) {
		seil s=new seil();
		
		Thread t1=new Thread(s,"窗口1");
		Thread t2=new Thread(s,"窗口2");
		Thread t3=new Thread(s,"窗口3");
		
		t1.start();
		t2.start();
		t3.start();
	}
public class seil implements Runnable {

	private static int tickets=100;
	//创建Lock接口对象
	 private Lock lock=new ReentrantLock();
	
	@Override
	public void run() {
		while(true) {
			try {
				lock.lock();//获取锁
				if(tickets>0) {
					try {
						Thread.sleep(100);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					System.out.println(Thread.currentThread().getName()
							+"正在售出第"+(tickets--)+"张票");
				}else {
					System.exit(0);
				}
				
			}finally {
				if(lock!=null) {
					//释放锁
					lock.unlock();
				}
			}
		}

	}

}

 

五.消费者生产者模式

1.
 

public static void main(String[]args) {
		student ss=new student();
		setStudent s=new setStudent(ss);
		getStudent g=new getStudent(ss);
		
		Thread d1=new Thread(s);
		Thread d2=new Thread(g);
		
		d1.start();
		d2.start();
		
		
	}
public class setStudent implements Runnable {

	private student s;
	
	public setStudent(student s) {
		super();
		this.s = s;
	}

	@Override
	public void run() {
		s.name="卜凡";
		s.age=22;
	}

}

 

public class getStudent implements Runnable {

	private student s;
	
	
	public getStudent(student s) {
		super();
		this.s = s;
	}


	@Override
	public void run() {
		System.out.println(s.name+" "+s.age);
	}

}

 

public class student {

	String name;
	int age;
}

2.

public static void main(String[]args) {
		student ss=new student();
		setStudent s=new setStudent(ss);
		getStudent g=new getStudent(ss);
		
		Thread d1=new Thread(s);
		Thread d2=new Thread(g);
		
		d1.start();
		d2.start();
		
}

 

public class setStudent implements Runnable {

	private student s;
	
	public setStudent(student s) {
		super();
		this.s = s;
	}
	
	private int x=0;
	/**
	 * 1)是否是多线程环境		是
 		2)是否有功共享数据		是
 		3)是否有多条语句对共享数据进行操作 	有
 			
 		同步机制(同步代码块/同步方法)
	 * */
	@Override
	public void run() {
		while(true) {
			synchronized(s) {//加入同步代码块
				if(x%2==0) {
					s.name="卜凡";
					s.age=22;
				}else {
					s.name="王子异";
					s.age=23;
				}
				x++;
			}
		}

	}

}

 

public class getStudent implements Runnable {

	private student s;
	
	public getStudent(student s) {
		super();
		this.s = s;
	}

	@Override
	public void run() {
		while(true) {
			System.out.println(s.name+" "+s.age);
		}

	}

}

 

public class student {
	String name;
	int age;
}


六.等待唤醒机制

public static void main(String[]args) {
		student ss=new student();
		setStudent s=new setStudent(ss);
		getStudent g=new getStudent(ss);
		
		Thread d1=new Thread(s);
		Thread d2=new Thread(g);
		
		d1.start();
		d2.start();

 

//生产者线程
public class setStudent implements Runnable {

	private student s;
	
	public setStudent(student s) {
		super();
		this.s = s;
	}

	private int x=0;
	@Override
	public void run() {
		while(true) {
			synchronized(s) {
				//资源类有数据,则生产者等待消费者消费,暂时不进行生产
				if(s.flag) {
					try {
						s.wait();
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
				//资源类没有数据了,则生产者进行生产
				if(x%2==0) {
					s.name="卜凡";
					s.age=22;
				}else {
					s.name="王子异";
					s.age=23;
				}
				x++;
				//产生数据后,将flag的值改变为true
				s.flag=true;
				//通知消费者消费
				s.notify();//唤醒后,t1,t2都互相等待
			}
		}
	}

}

 

//消费者线程
public class getStudent implements Runnable {

	private student s;
	
	public getStudent(student s) {
		super();
		this.s = s;
	}

	@Override
	public void run() {
		while(true) {
			synchronized(s) {
				//资源类没有数据了
				//消费者等待
				if(!s.flag) {
					try {
						s.wait();
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					//资源类有数据,则消费者输出
					System.out.println(s.name+" "+s.age);
					//资源消费完了,将flag置为false
					//通知生产者没有数据了,让生产者生产数据
					s.flag=false;
					s.notify();
				}
			}
		}

	}

}

 

//资源类
public class student {

	String name;
	int age;
	boolean flag;
}


七.线程组

线程组是一个线程的集合,线程组也可以包含其他线程组

public static void main(String[]args) {
		ThreadGroup tp=new ThreadGroup("新的线程组");
		MyThread m=new MyThread();
		
		Thread t1=new Thread(tp,m,"线程1");
		Thread t2=new Thread(tp,m,"线程2");
		
		t1.start();
		t2.start();
		
		System.out.println(t1.getThreadGroup().getName());
		System.out.println(t2.getThreadGroup().getName());
		
	}

 

public class MyThread implements Runnable{

	@Override
	public void run() {
		for(int i=0;i<67;i++) {
			System.out.println(Thread.currentThread().getName()+" "+i);
		}
		
	}

	
}


八.线程池

1.线程池

 

	public static void main(String[]args) {
		ExecutorService pool = Executors.newFixedThreadPool(2);
		pool.submit(new MyRunnable());
		pool.submit(new MyRunnable());
		pool.shutdown();
		
	}

 

public class MyRunnable implements Runnable {

	@Override
	public void run() {
		for(int i=0;i<97;i++) {
			System.out.println(Thread.currentThread().getName()+" "+i);
		}

	}

}

 

 

2.future

private static Future<Integer> future;

	public static void main(String[]args) throws InterruptedException, ExecutionException {
		//创建线程池对象
		ExecutorService pool = Executors.newFixedThreadPool(2);
		//提交任务
		Future<Integer> f1=  pool.submit(new MyCallable(100));
		Future<Integer> f2=  pool.submit(new MyCallable(200));
		
		//获取结果
		Integer i1=f1.get();
		Integer i2=f2.get();
		System.out.println(i1);
		System.out.println(i2);
		
		//关闭线程池
		pool.shutdown();
		
	}

 

public class MyCallable implements Callable<Integer> {

	private int num;
	
	public MyCallable(int num) {
		super();
		this.num = num;
	}

	@Override
	public Integer call() throws Exception {
		int sum=0;
		for(int i=0;i<num;i++) {
			sum+=i;
		}
		
		return sum;
	}

}

 

 

 

九.多线程的第三种实现方式

多线程实现方式第三种:
 
  前提:自定义类实现Callable接口
   1)创建线程池对象: Executors 里面的那个方法,返回的是ExecutorsService
   2) 然后调用ExecutorsService里面的提交任务的方法:
  <T> Future<T> submit(Callable<T> task)提交一个返回值的任务用于执行
   3)关闭线程池

public static void main(String[]args) {
		//创建线程池对象
		ExecutorService pool = Executors.newFixedThreadPool(2);
		//调用提交方法
		pool.submit(new MyCallable());
		pool.submit(new MyCallable());
		
		pool.shutdown();
		
	}

 

public class MyCallable implements Callable {

	@Override
	public Object call() throws Exception {
		for(int i=0;i<97;i++) {
			System.out.println(Thread.currentThread().getName()+" "+i);
		}
		return null;
	}

}



 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值