标签:管程 flag tran 对象 强制 timeout watch public 机制
进程:正在执行的程序。
线程:可以理解成进程中独立运行的子任务,一个进程至少有一个线程。
多线程:一个进程中有多个线程。
继承Thread类。
public class TestThread extends Thread{
@Override
//重写run方法
public void run() {
for (int i = 0; i < 20; i++) {
System.out.println("我在学习"+(i+1));
}
}
public static void main(String[] args) {
TestThread testThread = new TestThread();
testThread.start();//调用start()方法实现多线程
for (int i = 0; i < 1000; i++) {
System.out.println("我在睡觉"+(i+1));
}
}
}
实现Runnable接口。
public class TestRunnable implements Runnable{
@Override
public void run() {
for (int i = 0; i < 20; i++) {
System.out.println("我在学习"+(i+1));
}
}
public static void main(String[] args) {
TestRunnable testRunnable = new TestRunnable();
new Thread(testRunnable).start();//代理
for (int i = 0; i < 1000; i++) {
System.out.println("我在睡觉"+(i+1));
}
}
}
通过Callable和Future创建线程。
public class TestCallable implements Callable<Boolean> {//自定义返回值,还可以抛出异常
@Override
public Boolean call() {
for (int i = 0; i < 1000; i++) {
System.out.println("我在学习"+(i+1));
}
return true;
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
TestCallable testCallable = new TestCallable();
//创建执行服务
ExecutorService ser = Executors.newFixedThreadPool(1);
//提交执行
Future<Boolean> result = ser.submit(testCallable);
for (int i = 0; i < 1000; i++) {
System.out.println("我在睡觉"+(i+1));
}
//获取结果
boolean r1 = result.get();
//关闭服务
ser.shutdownNow();
}
}
Thread.sleep(1000)
:线程休眠1s。Thread.yield()
:礼让看CPU心情。Thread.join()
:等到此线程执行完,再执行其他线程。Thread.State
NEW
尚未启动的线程处于此状态。
RUNNABEL
在Java虚拟机中执行的线程处于此状态
BLOCKED
被阻塞等待监视器锁定的线程处于此状态。
WAITTING
正在等待另一个线程执行特定动作的线程处于此状态。
TIMED_WAITTING
正在等待另一个线程执行动作达到指定等待时间的线程处于此状态。
TERMINATED
已退出的线程处于此状态。
线程的优先级用数字表示,范围从1~10。
使用getPriority()、setPriority()获取或者改变优先级。
优先级低只是意味着获得CPU调度的概率低。
线程分为用户线程和守护线程。
虚拟机必须确保用户线程执行完毕。
虚拟机不用等待守护线程执行完毕。
thread.setDaemon(true)
:设置为守护线程。
不安全的买票:
public class UnsafeBuyTicket {
public static void main(String[] args) {
BuyTicket station = new BuyTicket();
new Thread(station,"小猪").start();
new Thread(station,"小鸡").start();
new Thread(station,"小狗").start();
}
}
class BuyTicket implements Runnable{
private int ticketNums = 10;
boolean flag = true;//外部停止方式
@Override
public void run() {
while(flag){
try {
buy();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void buy() throws InterruptedException {
if(ticketNums <= 0){
flag = false;
return;
}
Thread.sleep(100);//模拟延时,放大问题的发生性
System.out.println(Thread.currentThread().getName()+"抢到第"+ticketNums--+"张票。");
}
}
不安全的取钱:
public class UnsafeBank {
public static void main(String[] args) {
Account account = new Account(100, "结婚基金");
Drawing me = new Drawing(account,50,"我");
Drawing anotherMe = new Drawing(account,100,"平行空间里的我");
me.start();
anotherMe.start();
}
}
//账户
class Account{
int money;
String name;
public Account(int money, String name){
this.name = name;
this.money = money;
}
}
//银行
class Drawing extends Thread{
int nowMoney;
Account account;
int drawingMoney;
String name;
public Drawing(Account account, int drawingMoney, String name){
super(name);
this.account = account;
this.drawingMoney =drawingMoney;
}
@Override
public void run() {
if(account.money-drawingMoney < 0){
System.out.println(Thread.currentThread().getName()+"钱不够,取不了!");
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
account.money = account.money-drawingMoney;
nowMoney = nowMoney+drawingMoney;
System.out.println(account.name+"余额为:"+account.money);
System.out.println(this.getName()+"手里的钱:"+nowMoney);
}
}
不安全的集合:
public class UnsafeList {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
for (int i = 0; i < 10000; i++) {
new Thread(()->{
list.add(Thread.currentThread().getName());
}).start();
}
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(list.size());
}
}
安全的买票:将买票方法设置为同步方法public synchronized void buy(){}
。
public class SafeBuyTicket {
public static void main(String[] args) {
BuyTicket station = new BuyTicket();
new Thread(station,"小猪").start();
new Thread(station,"小鸡").start();
new Thread(station,"小狗").start();
}
}
class BuyTicket implements Runnable{
private int ticketNums = 10;
boolean flag = true;//外部停止方式
@Override
public void run() {
while(flag){
try {
buy();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public synchronized void buy() throws InterruptedException {
if(ticketNums <= 0){
flag = false;
return;
}
Thread.sleep(100);//模拟延时,放大问题的发生性
System.out.println(Thread.currentThread().getName()+"抢到第"+ticketNums--+"张票。");
}
}
安全的取钱:用同步代码块锁住Account对象。
public class SafeBank {
public static void main(String[] args) {
Account account = new Account(100, "结婚基金");
Drawing me = new Drawing(account,50,"我");
Drawing anotherMe = new Drawing(account,100,"平行空间里的我");
me.start();
anotherMe.start();
}
}
//账户
class Account{
int money;
String name;
public Account(int money, String name){
this.name = name;
this.money = money;
}
}
//银行
class Drawing extends Thread{
int nowMoney;
Account account;
int drawingMoney;
String name;
public Drawing(Account account, int drawingMoney, String name){
super(name);
this.account = account;
this.drawingMoney =drawingMoney;
}
@Override
public void run() {
synchronized (account){
if(account.money-drawingMoney < 0){
System.out.println(Thread.currentThread().getName()+"钱不够,取不了!");
return;
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
account.money = account.money-drawingMoney;
nowMoney = nowMoney+drawingMoney;
System.out.println(account.name+"余额为:"+account.money);
System.out.println(this.getName()+"手里的钱:"+nowMoney);
}
}
}
安全的集合:用同步代码块锁住List对象,这里也可以用线程安全的CopyOnWriteArrayList
集合。
public class SafeList {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
for (int i = 0; i < 10000; i++) {
new Thread(()->{
synchronized(list){
list.add(Thread.currentThread().getName());
}
}).start();
}
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(list.size());
}
}
产生死锁的四个必要条件:
从JDK 5.0 开始,Java提供了更强大的线程同步机制,通过显示定义同步锁对象来实现同步。同步锁使用Lock对象。
锁提供了对共享资源的独占访问,每次只能有一个线程对Lock对象加锁,线程开始访问共享资源之前应先获得Lock对象。
ReentrantLock(可重入锁)类实现了Lock,它拥有了与synchronized相同的并发性和内存语义,在实现线程安全的控制中,比较常用的是ReentrantLock,可以显式加锁、释放锁。
private final ReentrantLock lock = new ReentrantLock();
lock.lock();
//业务逻辑...
lock.unlock();//如果同步代码有异常,可以将解锁操作放到try...catch的finally里
synchronized和Lock的区别:
Java提供了几个方法来解决线程之间的通信问题。
方法名 | 作用 |
---|---|
wait() | 表示线程一直等待,直到其他线程通知,与sleep不同,会释放锁。 |
wait(long timeout) | 指定等待的毫秒数。 |
notify() | 唤醒一个处于等待状态的线程。 |
notifyAll() | 唤醒同一个对象上所有调用wait()方法的线程,优先级高的线程优先调度。 |
生产者消费者模式:
管程法(利用缓冲区)
public class PAC {
public static void main(String[] args) {
Container container = new Container();
new Producer(container).start();
new Customer(container).start();
}
}
class Producer extends Thread{
Container container;
public Producer(Container container){
this.container = container;
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
container.push(new Chicken(i));
System.out.println("生产了"+i+"只鸡");
}
}
}
class Customer extends Thread{
Container container;
public Customer(Container container){
this.container = container;
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("消费了"+container.pop().id+"只鸡");
}
}
}
class Chicken{
int id;
public Chicken(int id) {
this.id = id;
}
}
class Container{
Chicken[] chickens = new Chicken[10];
int cnt = 0;
public synchronized void push(Chicken chicken){
//如果容器满了,等待消费者消费
if(cnt == chickens.length){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
chickens[cnt] = chicken;
cnt++;
this.notifyAll();
}
public synchronized Chicken pop(){
//判断能否消费
if(cnt == 0){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
cnt--;
Chicken chicken = chickens[cnt];
this.notifyAll();
return chicken;
}
}
信号灯法(利用标志位)
public class PAC2 {
public static void main(String[] args) {
TV tv = new TV();
new Performer(tv).start();
new Viewer(tv).start();
}
}
class Performer extends Thread{
private TV tv;
public Performer(TV tv){
this.tv = tv;
}
@Override
public void run() {
for (int i = 0; i < 20; i++) {
if(i%2 == 0){
this.tv.perform("小猪佩奇");
}else{
this.tv.perform("哆啦A梦");
}
}
}
}
class Viewer extends Thread{
private TV tv;
public Viewer(TV tv){
this.tv = tv;
}
@Override
public void run() {
for (int i = 0; i < 20; i++) {
tv.watch();
}
}
}
class TV{
private String program;
boolean flag = true;
public synchronized void perform(String program){
if(!flag){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("演员表演了"+program);
this.notifyAll();
this.program = program;
this.flag = !this.flag;
}
public synchronized void watch(){
if(flag){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("观众观看了"+program);
this.notifyAll();
this.flag = !this.flag;
}
}
提前创建好多个线程,放入线程池,使用时直接获取,使用完放回池中。
使用线程池的好处:
JDK 5.0起提供了线程池相关的API:ExecutorService和Executors。
public class ThreadPool {
public static void main(String[] args) {
ExecutorService service = Executors.newFixedThreadPool(10);//创建容量为10的线程池
service.execute(new Thread(()->{System.out.println(Thread.currentThread().getName());}));//开启线程
service.execute(new Thread(()->{System.out.println(Thread.currentThread().getName());}));
service.execute(new Thread(()->{System.out.println(Thread.currentThread().getName());}));
service.shutdown();
}
}
标签:管程 flag tran 对象 强制 timeout watch public 机制
原文地址:https://www.cnblogs.com/baihan/p/12994181.html