黑马程序员——Java基础——多线程

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

多线程
进程和线程的区别
1.进程:在执行的程序

             每一个进程都有一个执行顺序,或者叫执行路径.或者控制单换

2.线程:进程的执行单元,执行路径

                   就是进程中的一个独立的控制单元

                   线程在控制的进程的执行

一个进程中至少有一个线程

建立进程的方式

1.继承Thread
//1.	继承Thread
//2.	覆盖run方法
//线程要运行的代码
//3.	执行start方法->>调用run方法
//start是父类的,调用子类的run方法(没有调用start方法)


class ExtendsThread extends Thread {

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


public class ExtendsThreadDemo {

	public static void main(String[] args) {
		
		Thread t1 = new ExtendsThread();
		Thread t2 = new ExtendsThread();
		t1.start();
		t2.start();
	}

}

2.实现Runnable接口
//1.	定义类实现Runnable接口
//2.	覆盖void run()方法
//3.	通过Thread建立线程对象
//4.	将Runnable 类的实现接口类的对象传入/Thread类
//5.	调用Thread的start方法

class ImplementsRunnable implements Runnable{

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


public class ImplementsRunnableDemo{
	public static void main(String[] args) {
		ImplementsRunnable ir = new ImplementsRunnable();
		Thread t1 = new Thread(ir);
		Thread t2 = new Thread(ir);
		
		t1.start();
		t2.start();
	}
}

3.使用线程池
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;

//1.实现Callable接口
//2.覆盖call方法
//3.获取线程池
//4.提交进程

class CallableDemo implements Callable<Integer>{

	int sum= 0;
	int number;
	
	public CallableDemo(int number) {
		this.number = number;
	}
	
	public Integer call() throws Exception {
		for(int i=0;i<=number;i++){
			sum+=i;
		}
		return sum;
	}
	
}



public class ThreadPoolCallableDemo {

	public static void main(String[] args) {
		ExecutorService es = Executors.newFixedThreadPool(2);
		Future<Integer> f1 = es.submit(new CallableDemo(100));
		Future<Integer> f2 = es.submit(new CallableDemo(200));
		try {
			System.out.println(f1.get());
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ExecutionException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		try {
			System.out.println(f2.get());
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ExecutionException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		es.shutdown();
	}

}

线程安全
建立方法

A:同步代码块
synchronized(对象) {
需要被同步的代码;
}
这里的锁对象可以是任意对象。

B:同步方法
把同步加在方法上。
这里的锁对象是this

C:静态同步方法
把同步加在方法上。

同步的前提

多个线程
多个线程使用的是同一个锁对象
同步的好处
同步的出现解决了多线程的安全问题。
同步的弊端
当线程相当多时,因为每个线程都会去判断同步上的锁,这是很耗费资源的,无形中会降低程序的运行效率。
死锁
双发都拿着对方需要资源,互不释放
<span style="font-size:12px;">//自定义锁
public class MyLock {
	static Object lock1 = new Object();
	static Object lock2 = new Object();
}
</span>
<span style="font-size:12px;">public class DeadLock implements Runnable {

	boolean flag;
	public DeadLock(boolean flag) {
		this.flag = flag;
	}
	//相互持锁,互不释放,产生死锁
	public void run() {
		while(true){
			if(flag){
				synchronized(MyLock.lock1){
					System.out.println("true lock1");
					synchronized (MyLock.lock2) {
						System.out.println("false lock2");
					}
				}	
			}else{
				synchronized(MyLock.lock2){
					System.out.println("false lock2");
					synchronized(MyLock.lock1){
						System.out.println("false lock1");
					}
				}
			}

		}
		
	}
	
}</span>
<span style="font-size:12px;">//主函数调用
public class Main {

	public static void main(String[] args) {
		Thread t1 = new Thread(new DeadLock(false));
		Thread t2 = new Thread(new DeadLock(true));
		
		t1.start();
		t2.start();
	}

}</span>


线程通信机制
1.传统的等待唤醒机制
public class Res {
	//模仿资源
	private String name;
	private String sex;
	//判断是否有资源
	private boolean flag = false;
	
	//设置资源
	public synchronized void set(String name,String sex){
		if(flag){//如果有资源的话等待
			try {
				wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		//设置资源
		this.name = name;
		this.sex = sex;
		//表示有
		flag = true;
		//唤醒全部
		notifyAll();
	}
	
	public synchronized void get(){//取资源
		if(!flag){//没有资源的话,等待
			try {
				wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		//输出资源
		System.out.println(name+"___"+sex);
		//设置等待
		flag = false;
		//全部唤醒
		notifyAll();
	
	}
}

public class Input implements Runnable{

	Res s;
	public Input(Res s) {
		this.s = s;
	}
	@Override
	public void run() {
		int flag = 0;
		while(true){
			//轮流设置资源
			if(flag == 0){
				s.set("lili", "female");
				flag = 1;
			}else{
				s.set("哈哈", "男");
				flag = 0;
			}
		}
		
	}

}

//取出资源
public class Output implements Runnable {
	Res s;

	public Output(Res s) {
		this.s = s;
	}

	@Override
	public void run() {
		while(true){
			s.get();
		}
		
	}
	
}

//主函数
public class Main {

	public static void main(String[] args) {
		Res s =new Res();
		
		Input i = new Input(s);
		Output o = new Output(s);
		
		Thread t1 = new Thread(i);
		Thread t2 = new Thread(o);
		
		t1.start();
		t2.start();

	}

}

2.新的加锁,等待唤醒

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
//资源类
public class Res {
	private String name;//商品名字
	private int count = 1;//商品数
	private boolean flag = false;//标志变量
	private Lock l = new ReentrantLock();//锁
	private Condition con1 = l.newCondition();//第一个限制
	private Condition con2 = l.newCondition();//第二个限制

	public void set(String name) {
		try {
			l.lock();//上锁
			if (flag) {
				try {
					con1.await();//con1等待
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			//赋值商品名字
			this.name = name;
			//输出存入商品名字
			System.out.println(Thread.currentThread().getName() + "__買入__"
					+ this.name + count++);
			flag = true;//记录有商品
			con2.signal();//唤醒con2
		} finally {
			l.unlock();//释放锁
		}
	}

	public void get() {
		try {
			l.lock();//上锁
			if (!flag) {
				try {
					con2.await();//con2等待
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			//输出取出商品
			System.out.println(Thread.currentThread().getName() + "買出"
					+ this.name + count);
			flag = false;//设置商品被取出
			con1.signal();//唤醒con1
		} finally {
			l.unlock();//释放所
		}
	}
}

//消费者
public class Cus implements Runnable {
	Res r;
	public Cus(Res r) {
		this.r = r;
	}
	//消费商品
	public void run() {
		while(true){
			//取出商品
			r.get();
		}
		
	}
}

//生产者
public class Pro implements Runnable{
	Res r;
	public Pro(Res r) {
		this.r = r;
	}
	@Override
	public void run() {
		while(true){
			//生产商品
			r.set("商品");
		}
		
	}
}

//调用主类
public class Main {
	public static void main(String[] args) {
		Res r = new Res();
		Cus c = new Cus(r);
		Pro p = new Pro(r);
		
		Thread t1 = new Thread(c);
		Thread t2 = new Thread(p);
		
		t1.start();
		t2.start();
	}
}

线程生命周期
新建 -- 就绪 -- 运行 -- 死亡
新建 -- 就绪 -- 运行 -- 阻塞 -- 就绪 -- 运行 -- 死亡


你可能感兴趣的:(java)