【JavaSE:1.多线程】

参考的博客原文:
Java中的多线程你只要看这一篇就够了(墙裂推荐这个链接,治好了多年的隐疾)

  1. 最初场景:生产者消费者模式
    模拟买票Ticket
package multiThread;

public class Ticket implements Runnable {
//共100票
	int ticket = 100;

	@Override
	public void run() {
//模拟卖票
		while (true) {
			if (ticket > 0) {
//模拟选坐的操作
				try {
					Thread.sleep(1);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println(Thread.currentThread().getName() + "正在卖票:" + ticket--);
			}
		}
	}
}

测试类ThreadDemo

package multiThread;

public class ThreadDemo {
	public static void main(String[] args) {
//创建票对象
		Ticket ticket = new Ticket();
//创建3个窗口s
		Thread t1 = new Thread(ticket, "窗口1");
		Thread t2 = new Thread(ticket, "窗口2");
		Thread t3 = new Thread(ticket, "窗口3");
		t1.start();
		t2.start();
		t3.start();
	}
}

===进阶版本

package multiThread;

import java.util.LinkedList;
import java.util.Queue;

/**
 * 
 * @author ziboris
 * @date 2018年11月23日 上午9:15:43
 *
 */

//1.queue的所有操作都会notifyAll 但是目前一定有一个线程触发这个notifyall
//其他线程因为还需要苏醒之后调度时间,肯定竞争不过他
//因此基本{产生满,同一个消费者消费完毕},{},{}....
//---》解决方案 在A出加上sleep代码块

public class ProducerConsumer {

	public static class Producer extends Thread {// 生产者阻塞时候是判满
		Queue<Integer> queue;
		int maxSize;

		public Producer(Queue<Integer> queue, int maxSize, String name) {
			this.queue = queue;
			this.maxSize = maxSize;
			this.setName(name);

			// TODO Auto-generated constructor stub
		}

		@Override
		public void run() {
			// TODO Auto-generated method stub
//			LinkedBlockingQueue<Integer> bQueue=new LinkedBlockingQueue<>();
			while (true) {
				// A
				try {
					Thread.sleep(500L);
				} catch (InterruptedException e) {
					e.printStackTrace();
					// TODO: handle exception
				}
				synchronized (queue) {

					System.out.println(this.getName() + " is in lock");
					if (queue.size() == maxSize) {
						System.out.println("queue is full--" + this.getName() + "--so waiting");
						try {
							queue.wait();// wait在queue这个资源上面 保存一份阻塞时候的状态,到时候被唤醒的时候可以直接往下面运行
						} catch (Exception e) {
							// TODO: handle exception
						}
					}
					int num = (int) (Math.random() * 100);
					queue.offer(num);// offer在加满的时候会返回一个false put会一直等待知道出现空位 add会抛出异常

					System.out.println(this.getName() + "-produce a ticket:-" + num);// 线程的子类可以用getname获取到初始化的name或者setname
					queue.notifyAll();// 因为其他被阻塞的线程都等待在queue这个资源上面

					System.out.println(" log out a produce");
				}
			}
		}
	}

	public static class Consumer extends Thread {
		Queue<Integer> queue;
		int maxSize;

		public Consumer(Queue<Integer> queue, int maxSize, String name) {
			// TODO Auto-generated constructor stub
			this.queue = queue;
			this.maxSize = maxSize;
			this.setName(name);
		}

		@Override
		public void run() {
			// TODO Auto-generated method stub
//			super.run();
			while (true) {
				try {
					Thread.sleep(200L);
				} catch (InterruptedException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
				synchronized (queue) {

					System.out.println(this.getName() + " is in lock");
					if (queue.isEmpty()) {
						System.out.println("queue is empty--" + this.getName() + "--so waiting");
						try {
							queue.wait();
						} catch (InterruptedException e) {
							// TODO: handle exception
							e.printStackTrace();
						}
					}
					int num = queue.poll();// queue的remove和poll都是去除第一个元素,空的时候一个是返回exception,null
					System.out.println(this.getName() + "- consume a ticket-" + num);
					queue.notifyAll();

					System.out.println(this.getName() + " log out a consume");
				}
			}
		}
	}

	public static void main(String[] args) {
		Queue<Integer> queue = new LinkedList<>();
		int maxSize = 10;

		Producer producer = new Producer(queue, maxSize, "Producer");
		Consumer consumer1 = new Consumer(queue, maxSize, "consumer1");
		Consumer consumer2 = new Consumer(queue, maxSize, "consumer2");
		Consumer consumer3 = new Consumer(queue, maxSize, "consumer3");
		producer.start();
		consumer1.start();
		consumer2.start();
		consumer3.start();
	}
}
  1. 并发和并行
并行多个cpu实例或者多台机器同时执行一段处理逻辑,是真正的同时
并发通过cpu调度算法,让用户看上去同时执行,实际上从cpu操作层面不是真正的同时。
  1. 线程状态与状态转换
    线程状态转换

  2. join
    下面程序如果不join:
    —Main Thread is finished
    Thread2 begins:Thu Nov 22 20:17:39 CST 2018
    Thread1 begins:Thu Nov 22 20:17:39 CST 2018
    Thread1 has finished: Thu Nov 22 20:17:44 CST 2018
    Thread2 has finished: Thu Nov 22 20:17:44 CST 2018
    发现main结束的时候两个子线程还没有启动好
    加上join(1,2先后随机)
    Thread2 begins:Thu Nov 22 20:20:02 CST 2018
    Thread1 begins:Thu Nov 22 20:20:02 CST 2018
    Thread2 has finished: Thu Nov 22 20:20:07 CST 2018
    Thread1 has finished: Thu Nov 22 20:20:07 CST 2018
    —Main Thread is finished

package multiThread;

import java.util.Date;
import java.util.concurrent.TimeUnit;

public class TestJoin implements Runnable {
	private String name;

	public TestJoin(String name) {
		this.name = name;
	}

	public void run() {
		System.out.printf("%s begins:%s\n", name, new Date());
		try {
			TimeUnit.SECONDS.sleep(5L);
		} catch (InterruptedException e) {
			e.printStackTrace();
			// TODO: handle exception
		}
		System.out.printf("%s has finished: %s\n", name, new Date());
	}

	public static void main(String[] args) {
		Thread thread1 = new Thread(new TestJoin("Thread1"));
		Thread thread2 = new Thread(new TestJoin("Thread2"));
		thread1.start();
		thread2.start();

//		try {
//			thread1.join();
//			thread2.join();
//		} catch (InterruptedException e) {
//			e.printStackTrace();
//			// TODO: handle exception
//		}

		System.out.println("---Main Thread is finished");
	}
}
  1. wait notify && notifyall

Causes the current thread to wait until another thread invokes
沉睡自己,知道其他线程唤醒自己 notify notifyall

线程在运行的时候,如果发现某些条件没有被满足,可以调用wait方法暂停自己的执行,并且放弃已经获得的锁,然后进入等待状态。当该线程被其他线程唤醒并获得锁后,可以沿着之前暂停的地方继续向后执行,而不是再次从同步代码块开始的地方开始执行。但是需要注意的一点是,对线程等待的条件的判断要使用while而不是if来进行判断。这样在线程被唤醒后,会再次判断条件是否正真满足。

  1. 基本线程类 Thread类,Runnable接口,Callable接口
    extends Thread还是implement runnable (二者基本类似 ,区别见下)
    参考博文:java创建线程implement runnable 和 extends thread 比较
    Thread(runnable):
//当前线程可转让cpu控制权,让别的就绪状态线程运行(切换)
public static Thread.yield()  
//yield()的作用是让步。它能让当前线程由“运行状态”进入到“就绪状态”,大家再次同一起跑线竞争
//暂停一段时间
public static Thread.sleep()  
//在一个线程中调用other.join(),将等待other执行完后才继续本线程。    
public join()
//后两个函数皆可以被打断
public interrupte()
  1. synchronized wait notify notifyAll 是任何对象都具有的方法,因为任何对象都是一个资源

java中每一个对象都有一个monitor监视器,只在多线程的时候发挥作用
synchronized wait notify 必须是针对同一个对象资源
每一个对象的monitor有一个进入队列和等待队列(实质上多等待着占有这个资源)

  1. volatile 多线程之间实时看见这个变量
    线程的创建的时候是将main线程内存load到自己的线程栈里面,完成run之后再save回去

volatile的作用是每一次的改变操作都会立马save回去 因此main中需要交给各个线程处理的变量要么是volatile 要么是final

  1. 高级多线层控制工具类:java.util.concurrent包里面since jdk1.5

ThreadLocal 为变量在每个线程中都创建了一个副本,那么每个线程可以访问自己内部的副本变量(如session)(墙裂推荐这个链接)
Atomic***(AtomicInteger AtomicBoolean)
Lock
容器类
管理类

【补充】

  1. 线程优先级:

Java线程可以有优先级的设定,高优先级的线程比低优先级的线程有更高的几率得到执行
优先级可以用从1到10的范围指定。10表示最高优先级,1表示最低优先级,5是普通优先级(default)

  1. 设置线程名字和线程组名字
    看线程出问题 jstack -pid 使用trycatch不行

线程组,批量管理多个线程

  1. Thread.currentThread()与this的区别
    参考资料:Thread.currentThread()与this的区别
    this 在类里面如论如何都指向这个类
    但是在这个自定义线程类中,只有run里面this和currentThread才相等
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值