黑马程序员——java基础学习笔记——第十一天

------ Java培训、Android培训、iOS培训、.Net培训 、期待与您交流! -------
多线程
一基本概念:
程序 (program)是为完成特定任务、用某种语言编写的一组指令的集合。即指 一段静态的代码,静态对象。
进程 (process)是程序的一次执行过程,或是 正在运行的一个 程序。动态过程:有它自身的产生、存在和消亡的过程。
如:运行中的QQ,运行中的MP3播放器
程序是静态的,进程是动态的
线程 (thread),进程可进一步细化为线程,是一个程序内部的一条执行路径。若一个程序可同一时间执行多个线程,就是支持多线程的。

创建线程的两种方式:
1.继承Thread类。
1.1定义子类继承Thread类。
1.2子类中重写Thread类中的run方法。
1.3创建Thread子类对象,即创建了线程对象。
1.4调用线程对象start方法:启动线程,调用run方法。

class SubThread extends Thread{
	public void run(){
		for(int i = 1;i <= 100;i++){
			System.out.println(Thread.currentThread().getName() +":" + i);
		}
	}
}

public class TestThread {
	public static void main(String[] args) {
		SubThread st1 = new SubThread();
		SubThread st2 = new SubThread();
		st1.start();
		st2.start();
		for(int i = 1;i <= 100;i++){
			System.out.println(Thread.currentThread().getName() +":" + i);
		}
	}
}


2实现Runnable接口

2.1定义子类,实现Runnable接口。

2.2子类中重写Runnable接口中的run方法。

2.3通过Thread类含参构造器创建线程对象。

2.4将Runnable接口的子类对象作为实际参数传递给Thread类的构造方法中。

2.5调用Thread类的start方法:开启线程,调用Runnable子类接口的run方法。


class PrintNum1 implements Runnable {
	public void run() {
		for (int i = 1; i <= 100; i++) {
			if (i % 2 == 0) {
				System.out.println(Thread.currentThread().getName() + ":" + i);
			}
		}
	}
}

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

三线程的生命周期:

要想实现多线程,必须在主线程中创建新的线程对象。Java语言使用Thread类及其子类的对象来表示线程,在它的一个完整的生命周期中通常要经历如下的五种状态:

新建: 当一个Thread类或其子类的对象被声明并创建时,新生的线程对象处于新建状态。

就绪:处于新建状态的线程被start()后,将进入线程队列等待CPU时间片,此时它已具备了运行的条件。

运行:当就绪的线程被调度并获得处理器资源时,便进入运行状态,run()方法定义了线程的操作和功能。

阻塞:在某种特殊情况下,被人为挂起或执行输入输出操作时,让出 CPU 并临时中止自己的执行,进入阻塞状态。

死亡:线程完成了它的全部工作或线程被提前强制性地中止。

黑马程序员——java基础学习笔记——第十一天_第1张图片













四线程的同步:
当多个线程操作共享数据时会出现安全问题
例题:模拟火车站售票窗口,开启三个窗口售票,总票数为100张。
class Window1 implements Runnable {
	int ticket = 100;

	public void run() {
		while (true) {
			if (ticket > 0) {
				try {
					Thread.currentThread().sleep(10);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println(Thread.currentThread().getName() + "售票,票号为:"+ ticket--);
			} else {
				break;
			}
		}
	}
}

public class TestWindow1 {
	public static void main(String[] args) {
		Window1 w = new Window1();
		Thread t1 = new Thread(w);
		Thread t2 = new Thread(w);
		Thread t3 = new Thread(w);
		
		t1.setName("窗口1");
		t2.setName("窗口2");
		t3.setName("窗口3");
		
		t1.start();
		t2.start();
		t3.start();
	}
}
此程序运行会出现0,-1等错票。解决办法: 对多条操作共享数据的语句,只能让一个线程都执行完,在执行过程中,其他线程不可以参与执行。 Java对于多线程的安全问题提供了专业的解决方式: 同步 机制。
1.synchronized(对象){

          需要被同步的代码;

    }

class Window2 implements Runnable {
	int ticket = 100;// 共享数据
	public void run() {
		while (true) {
			synchronized (this) {//this表示当前对象,本题中即为w
				if (ticket > 0) {
					try {
						Thread.currentThread().sleep(10);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					System.out.println(Thread.currentThread().getName()
							+ "售票,票号为:" + ticket--);
				}
			}
		}
	}
}

public class TestWindow2 {
	public static void main(String[] args) {
		Window2 w = new Window2();
		Thread t1 = new Thread(w);
		Thread t2 = new Thread(w);
		Thread t3 = new Thread(w);

		t1.setName("窗口1");
		t2.setName("窗口2");
		t3.setName("窗口3");

		t1.start();
		t2.start();
		t3.start();
	}
}


2.synchronized还可以放在方法声明中,表示整个方法

      为同步方法。

class Window4 implements Runnable {
	int ticket = 100;// 共享数据

	public void run() {
		while (true) {
			show();
		}
	}

	public synchronized void show() {
		
		if (ticket > 0) {
			try {
				Thread.currentThread().sleep(10);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName() + "售票,票号为:"
					+ ticket--);
		}

	}
}

public class TestWindow4 {
	public static void main(String[] args) {
		Window4 w = new Window4();
		Thread t1 = new Thread(w);
		Thread t2 = new Thread(w);
		Thread t3 = new Thread(w);

		t1.setName("窗口1");
		t2.setName("窗口2");
		t3.setName("窗口3");

		t1.start();
		t2.start();
		t3.start();
	}
}


死锁: 不同的线程分别占用对方需要的同步资源不放弃,都在等待对方放弃自己需要的同步资源,就形成了线程的死锁。
public class TestDeadLock {
	static StringBuffer sb1 = new StringBuffer();
	static StringBuffer sb2 = new StringBuffer();

	public static void main(String[] args) {
		new Thread() {
			public void run() {
				synchronized (sb1) {
					try {
						Thread.currentThread().sleep(10);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					sb1.append("A");
					synchronized (sb2) {
						sb2.append("B");
						System.out.println(sb1);
						System.out.println(sb2);
					}
				}
			}
		}.start();

		new Thread() {
			public void run() {
				synchronized (sb2) {
					try {
						Thread.currentThread().sleep(10);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					sb1.append("C");
					synchronized (sb1) {
						sb2.append("D");
						System.out.println(sb1);
						System.out.println(sb2);
					}
				}
			}
		}.start();
	}

}

五线程的通信。
wait() notify() notifyAll ()
wait():令当前线程挂起并放弃CPU、同步资源,使别的线程可访问并修改共享资源,而当前线程排队等候再次对资源的访问。
notify():唤醒正在排队等待同步资源的线程中优先级最高者结束等待。
notifyAll():唤醒正在排队等待资源的所有线程结束等待。
Java.lang.Object提供的这三个方法只有在synchronized方法或synchronized代码块中才能使用,否则会报 java.lang.IllegalMonitorStateException异常。
例题:生产者消费者。
class Clerk{//店员
int product;

public synchronized void addProduct(){//生产产品
if(product >= 20){
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}else{
product++;
System.out.println(Thread.currentThread().getName() + ":生产了第" + product + "个产品");
notifyAll();
}
}
public synchronized void consumeProduct(){//消费产品
if(product <= 0){
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}else{
System.out.println(Thread.currentThread().getName() + ":消费了第" + product + "个产品");
product--;
notifyAll();
}
}
}


class Producer implements Runnable{//生产者
Clerk clerk;

public Producer(Clerk clerk){
this.clerk = clerk;
}
public void run(){
System.out.println("生产者开始生产产品");
while(true){
try {
Thread.currentThread().sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
clerk.addProduct();

}
}
}
class Consumer implements Runnable{//消费者
Clerk clerk;
public Consumer(Clerk clerk){
this.clerk = clerk;
}
public void run(){
System.out.println("消费者消费产品");
while(true){
try {
Thread.currentThread().sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
clerk.consumeProduct();
}
}
}




public class TestProduceConsume {
public static void main(String[] args) {
Clerk clerk = new Clerk();
Producer p1 = new Producer(clerk);
Consumer c1 = new Consumer(clerk);
Thread t1 = new Thread(p1);//一个生产者的线程
Thread t2 = new Thread(p1);
Thread t3 = new Thread(c1);//一个消费者的线程

t1.setName("生产者1");
t2.setName("生产者2");
t3.setName("消费者1");

t1.start();
t2.start();
t3.start();
}
}







你可能感兴趣的:(黑马程序员——java基础学习笔记——第十一天)