实验目的与要求:
实验目的: 掌握Java程序设计中的线程同步等技术。
实验要求:
(1). 编写Java应用程序实现如下功能:第一个线程生成一个随机数,第二个线程每隔一段时间读取第一个线程生成的随机数,并判断它是否是素数。在报告中附上程序截图、完整的运行结果和简要文字说明。(30分)
(2). 编写Java应用程序实现如下功能:第一个线程输出数字1-52,第二个线程输出字母A-Z,输出的顺序为12A34B56C...5152Z。要求线程间实现通信。在报告中附上程序截图、运行结果和详细的文字说明。(30分)
(3). 编写Java应用程序实现如下功能:创建工作线程,模拟银行现金账户取款操作。多个线程同时执行取款操作时,如果不使用同步处理,会造成账户余额混乱,要求使用syncrhonized关键字同步代码块,以保证多个线程同时执行取款操作时,银行现金账户取款的有效和一致。在报告中附上程序截图、运行结果和详细的文字说明。(40分)
(1). 编写Java应用程序实现如下功能:第一个线程生成一个随机数,第二个线程每隔一段时间读取第一个线程生成的随机数,并判断它是否是素数。在报告中附上程序截图、完整的运行结果和简要文字说明。(30分)
设计:为了线程安全,采用LinkedBlockingQueue链式阻塞队列作为缓冲区,实现PrimeGen类和PrimeChecker类
package Hw8;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Random;
import java.util.Timer;
import java.util.concurrent.LinkedBlockingQueue;
class PrimeGen extends Thread {
public Random random = new Random();
public LinkedBlockingQueue<Integer> lbq;
PrimeGen(LinkedBlockingQueue<Integer> lbq) {
this.lbq = lbq;
}
@Override
public void run() {
try {
while (true) {
int temp = random.nextInt() % 1000;
if (temp < 0) {
temp = -temp;
}
lbq.put(temp);
}
} catch (Exception e) {
System.out.println("PrimeGen终止");
}
}
}
class PrimeChecker extends Thread {
public LinkedBlockingQueue<Integer> lbq;
PrimeChecker(LinkedBlockingQueue<Integer> lbq) {
this.lbq = lbq;
}
public boolean isPrime(int temp) {
for (int i = 2; i < temp; i++) {
if (temp % i == 0) {
return false;
}
}
return true;
}
@Override
public void run() {
try {
while (true) {
Integer temp = lbq.take();
if (isPrime(temp)) {
System.out.println(temp + "是质数");
}
}
} catch (Exception e) {
System.out.println("PrimeChecker终止");
}
}
}
public class PrimeTest {
public static void main(String[] args) throws InterruptedException {
LinkedBlockingQueue<Integer> lbq = new LinkedBlockingQueue<>();
PrimeGen primeGen = new PrimeGen(lbq);
PrimeChecker primeChecker = new PrimeChecker(lbq);
primeGen.start();
primeChecker.start();
try {
Thread.sleep(100);
} catch (Exception e) {
System.out.println(e.getMessage());
}
primeGen.interrupt();
primeChecker.interrupt();
}
}
(2). 编写Java应用程序实现如下功能:第一个线程输出数字1-52,第二个线程输出字母A-Z,输出的顺序为12A34B56C...5152Z。要求线程间实现通信。在报告中附上程序截图、运行结果和详细的文字说明。(30分)
设计:采用锁的思想,第一个线程执行两次的时候就释挂起并且唤醒其他线程,第二个线程同理
package Hw8;
import java.io.ObjectStreamException;
public class Sem {
public static void main(String[] args) {
Object lock = new Object();
NumGen numGen = new NumGen(lock);
CharGen charGen = new CharGen(lock);
new Thread(numGen,"numGen").start();
new Thread(charGen,"charGen").start();
}
}
class NumGen implements Runnable{
Object lock;
int cnt = 0;
NumGen(Object lock){
this.lock = lock;
}
@Override
public void run(){
synchronized (lock){
while(true){
cnt++;
System.out.print(cnt);
cnt++;
System.out.print(cnt);
if(cnt==52){
lock.notifyAll();
break;
}
lock.notifyAll();
try {
lock.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
}
class CharGen implements Runnable{
Object lock;
char aChar = 'A';
CharGen(Object lock){
this.lock = lock;
}
@Override
public void run(){
synchronized (lock){
while(true){
System.out.print(aChar);
if(aChar=='Z'){
break;
}
aChar++;
lock.notifyAll();
try {
lock.wait();
}catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
}
(3). 编写Java应用程序实现如下功能:创建工作线程,模拟银行现金账户取款操作。多个线程同时执行取款操作时,如果不使用同步处理,会造成账户余额混乱,要求使用syncrhonized关键字同步代码块,以保证多个线程同时执行取款操作时,银行现金账户取款的有效和一致。在报告中附上程序截图、运行结果和详细的文字说明。(40分)
设计:通过给取钱动作加锁,来实现线程同步
package Hw8;
public class Bank {
int total;
Bank(){
total = 10000;
}
public boolean isEmpty(){
return total <= 0;
}
public synchronized void take(){
if(total>100){
total-=100;
System.out.println("现在的余额是"+total);
}
else{
total = 0;
System.out.println("别取拉!要没钱拉!");
}
}
public static void main(String[] args) {
Bank bank = new Bank();
User[] users = new User[8];
for (User user : users) {
user = new User(bank);
new Thread(user).start();
}
}
}
class User implements Runnable{
Bank bank;
User(Bank bank){
this.bank = bank;
}
@Override
public void run(){
while (!bank.isEmpty()) {
bank.take();
}
}
}