Java 线程同步问题初体验

本文介绍Java多线程相关知识,包括synchronized、wait()、notify()等方法的作用,进程运行需获得锁。阐述了双线程和多线程两类问题,针对不同任务场景给出解决思路,并通过实例展示双线程不同任务、多线程完成同一任务、多线程按顺序完成不同任务的代码实现。

初步认识:
1、synchronized 被访问时自动获取所在对象的锁。
2、wait() 使当前进程进入阻塞状态并释放锁。
3、notify() / notifyAll() 唤醒处于阻塞状态的进程。
4、进程要获得锁才能运行

两类线程问题:
双线程和多线程(3个及以上)

只执行同一任务,使用synchronized同步即可,
多任务需要配合wait()、notify() / notifyAll()

注意两点:
1 循环表达式3的位置要和目的执行语句同步执行。
2 明确目的执行语句
是要不满足条件且wait()后就可执行(双线程不同任务,另一线程使得满足条件)
还是要同步执行(多线程同任务)
还是只在满足条件时执行(多线程不同任务)。

1、双线程不同任务
实例2 写2个线程,其中一个线程打印1~26,另一个线程打印A~Z,1对A,2对B。
这个问题在不满足条件后wait()就可执行是因为,只有两个线程,且一个线程执行后,一定会使另一个线程满足条件。
代码:

import java.util.*;
import java.io.*;

class chik {
	int i = 1;
	private boolean isOk = true;
	
	public synchronized void ptN() {
		if(isOk == false) {
			try {
				wait();
			} catch (Exception e) {
				// TODO: handle exception
				e.printStackTrace();
			}
		}
		System.out.print(i);
		isOk = false;
		notify();
	}
	
	public synchronized void ptC() {
		if(isOk == true) {
			try {
				wait();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		System.out.println((char)(i + 64));
		i++;
		isOk = true;
		notify();
		}
}

class ptN extends Thread {
	chik ck;
		
	public ptN(chik ck) {
		this.ck = ck;
	}
	@Override
	public void run() {
		for(int i = 0; i < 26;i++)
			ck.ptN();
	}
}

class ptC extends Thread{
	chik ck;
	
	public ptC(chik ck) {
		this.ck = ck;
	}
	@Override
	public void run() {
		//此循环也可以放在ck类里面
		for(int i = 0; i < 26;i++)
			ck.ptC();
	}
}
public class Main {
	public static void main(String [] args) {
		chik ck = new chik();
		ptN pn = new ptN(ck);
		ptC pc = new ptC(ck);
		pn.start();
		pc.start();
	}
}

在这里插入图片描述

2、多线程完成同一任务
问题实例:
实例1 一个计数器,计数0到19,在每个数字之间暂停1秒,每隔10个数字输出一个字符串。

代码:

import java.util.*;
import java.io.*;

class Counter{
	int x;
	public Counter() {}
	public Counter(int x) {
		this.x = x;
	}
}

class RunTd implements Runnable{
	Counter counter;
	
	public RunTd() {}
	public RunTd(Counter counter) {
		super();
		this.counter = counter;
	}
	
	public void run() {
		print();
	}
	public void print() {
		synchronized(counter) {
			for(;counter.x < 20;counter.x++) {
				if(counter.x % 10 == 0) System.out.println("------" + counter.x);
				System.out.println(counter.x + "线程睡眠1毫秒!");
			}
			try {
				Thread.sleep(1);
			} catch (Exception e) {
				// TODO: handle exception
				e.printStackTrace();
			}
		}
	}
}

class Main{
    public static void main(String[] args) {
    	Counter count = new Counter(0);
    	new Thread(new RunTd(count)).start();
    	new Thread(new RunTd(count)).start();
    	new Thread(new RunTd(count)).start();
    }
}

在这里插入图片描述

3、多线程按顺序完成不同任务
问题描述实例:
启动3个线程 要求为每个线程单独输输入一个字符或字符串, 并按顺序输出三次,例线程1输入a,线程2输入b,线程三输入c,要求结果输出是a b c a b c a b c 这种连续的字符串(最后c后面有一个空格)

代码:

import java.util.*;
import java.io.*;

class Counter{
	int x;

	public Counter() {}
	public Counter(int x) {
		this.x = x;
	}
}

class RunTd implements Runnable{
	Counter counter;
	String str;
	int id;
	
	public RunTd(Counter counter, String str, int id) {
		super();
		this.counter = counter;
		this.str = str;
		this.id = id;
	}
	@Override
	public void run() {
		print();
	}
	public void print() {
		synchronized(counter) {
		//*****输出后i再++,!=id就不输出*****
		//此循环若放在counter里面,会漏掉一些值
			for(int i = 0;i < 3;) {
				if(counter.x != id) 
					try {
						counter.wait();
					} catch (Exception e) {
						// TODO: handle exception
						e.printStackTrace();
					}
				else {
					System.out.print(str + " ");
					counter.x = (counter.x + 1) % 4;
					if(counter.x == 0) counter.x = 1;
					i++;
					counter.notifyAll();
				}
			}
		}
	}
}

public class Main{
    public static void main(String[] args) {
    	Scanner sc = new Scanner(System.in);
    	Counter count = new Counter(1);
		new Thread(new RunTd(count, sc.next(), 1)).start();
    	new Thread(new RunTd(count, sc.next(), 2)).start();
    	new Thread(new RunTd(count, sc.next(), 3)).start();
  
    	sc.close();
    }
}

输入A B C
在这里插入图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值