这里写目录标题
1.volatile关键字有什么作用?
书中介绍:Java总是从主存读取变量,但随着JVM的优化,线程可以把主存变量保存在寄存器(工作内存)中操作,线程结束再与主存变量进行同步,然而当线程没有执行结束就发生了互换这就可能造成一个线程在主存中修改了一个变量的值,而另外一个线程还继续使用它在寄存器变量值的副本,造成数据的不一致。要解决这个问题就需要该变量声明为volatile(不稳定),它指示JVM这个变量是不稳定的,每次使用它都到主存中读取。
补充:在Java内存模型中,允许编译器和处理器对指令进行重排序,但是重排序过程不会影响到单线程程序的执行,却会影响到多线程并发执行的正确性。volatile关键字能禁止指令重排序,能在一定程度上保证有序性。
(参考博客:https://www.cnblogs.com/ustc-anmin/p/11434769.html)
例:
//变量a为volatile型,其他变量不是
b=1; //语句1
c=2; //语句2
a=5; //语句3
d=6; //语句4
e=4; //语句5
能保证语句3在语句1和语句2之后,语句4和语句5之前执行,但不能保证语句1、2和语句4、5的执行顺序。
2.编写Java程序模拟烧水泡茶最优工序。
package homework.third;
public class MakeTea {
public static void main(String[] args) {
MakeTeaThread1 mk1=new MakeTeaThread1();
mk1.start();
}
}
package homework.third;
public class MakeTeaThread1 extends Thread{
private MakeTeaThread2 mk2;
public MakeTeaThread1() {
mk2=new MakeTeaThread2();
}
public void run() {
System.out.print(this.getName()+":洗水壶->");
try {
Thread.sleep(1000);
}
catch(Exception e) {}
System.out.println("烧水-------------------");
System.out.print(" |");
mk2.start();
try {
Thread.sleep(15000);
}
catch(Exception e) {}
System.out.println();
System.out.print(Thread.currentThread().getName()+": 泡茶");
}
}
package homework.third;
public class MakeTeaThread2 extends Thread{
public void run() {
System.out.println();
System.out.print(this.getName()+": 洗茶壶->");
try {
Thread.sleep(1000);
}
catch(Exception e) {}
System.out.print("洗茶杯->");
try {
Thread.sleep(2000);
}
catch(Exception e) {}
System.out.println("拿茶叶------");
System.out.print(" ↓");
}
}
结果:
3. 编写一个基于多线程的生产者/消费者Java应用,各产生10个生产者和消费者线程,共享一个缓冲区队列(长度自设),生产者线程将产品放入到缓冲区,消费者线程从缓冲区取出产品。
package homework.third;
public class Products {
volatile private int product=0;
private Integer flag;
Products(){
flag=new Integer(1);
}
public int getProduct() {
return product;
}
public void produceProduct(int a) {
synchronized(flag) {
if(product<100) {
if(product+a>100) {
int b=a;
a=100-product;
product=100;
System.out.println(Thread.currentThread().getName()+"produce "+b+", produce too many only accept"+a+"; Products:"+product);
}else {
product+=a;
System.out.println(Thread.currentThread().getName()+" produce "+a+"; Products:"+product);
}
}
}
}
public void consumeProduct(int a) {
synchronized(flag) {
if(product>0) {
if(product-a<0) {
int b=product;
product=0;
System.out.println(Thread.currentThread().getName()+"consume "+a+", consume too maney only supply"+b+"; Products:"+product);
}else {
product-=a;
System.out.println(Thread.currentThread().getName()+" consume "+a+"; Products:"+product);
}
}
}
}
public static void main(String[] args) {
Products pr=new Products();
Producer[] p;
p=new Producer[10];
for(int i=0;i<10;i++) {
p[i]=new Producer(pr);
}
Consumer[] c;
c=new Consumer[10];
for(int i=0;i<10;i++) {
c[i]=new Consumer(pr);
}
for(int i=0;i<10;i++) {
p[i].start();
}
for(int i=0;i<10;i++) {
c[i].start();
}
}
}
package homework.third;
import java.util.*;
public class Producer extends Thread{
private Products p;
private Random ra;
Producer(Products p){
this.p=p;
ra=new Random();
}
public void run() {
int a;
while(true) {
a=ra.nextInt(Integer.MAX_VALUE)%10;
p.produceProduct(a);
}
}
}
package homework.third;
import java.util.*;
public class Consumer extends Thread{
private Products p;
private Random ra;
Consumer(Products p){
this.p=p;
ra=new Random();
}
public void run() {
int a;
while(true) {
a=ra.nextInt(Integer.MAX_VALUE)%10;
p.consumeProduct(a);
}
}
}
生产者生产的最大数量为:100
一次运行的部分结果: