Classic operation case between threads-producer and consumer case
Basic program model:
package Project.Study.Multithreading;
class Message{
private String title; //保存信息的标题
private String content; //保存信息的内容
public void setTitle(String title) {
this.title = title;
}
public void setContent(String content) {
this.content = content;
}
public String getTitle() {
return title;
}
public String getContent() {
return content;
}
}
class Producer implements Runnable{ //定义生产者
private Message msg=null;
public Producer(Message msg){
this.msg=msg;
}
@Override
public void run(){
for (int x=0;x<50;x++){ //生产50次数据
if(x%2==0){
this.msg.setTitle("小关"); //定义title属性
try {
Thread.sleep(100); //延迟操作
}catch (InterruptedException e){
e.printStackTrace();
}
this.msg.setContent("学习Java");//设置content属性
}else{
this.msg.setTitle("小梁"); //设置title属性
try {
Thread.sleep(100); //延迟操作
}catch (InterruptedException e){
e.printStackTrace();
}
this.msg.setContent("学习python");//设置content属性
}
}
}
}
class Consumer implements Runnable{
private Message msg;
public Consumer(Message msg){
this.msg=msg;
}
@Override
public void run(){
for(int x=0;x<50;x++){
try{
Thread.sleep(100);
}catch (InterruptedException e){
e.printStackTrace();
}
System.out.println(this.msg.getTitle()+"-->"+this.msg.getContent());
}
}
}
public class Test10 {
public static void main(String []args){
Message msg=new Message();
new Thread(new Producer(msg)).start();
new Thread(new Consumer(msg)).start();
}
}
//结果:
//小梁-->学习Java
//小关-->学习python
//小梁-->学习Java
//小关-->学习python
//小梁-->学习Java
//小关-->学习python
//小梁-->学习Java
//小关-->学习python
//小梁-->学习Java
//(...)
Originally the expected output of the program is: Xiaoguan-> learning Java, Xiaoliang-> learning python
but obviously there is a problem, the set data is misaligned, the data is repeatedly taken out and set repeatedly.
Solve the problem of data disorder
The data misalignment is entirely due to asynchronous operations, so synchronous processing should be used.
Example: Join the synchronization to solve the problem of data disorder
package Project.Study.Multithreading;
class Message2{
private String title; //保存信息的标题
private String content; //保存信息的内容
public synchronized void set(String title,String content){
this.title=title;
try{
Thread.sleep(100);
}catch(InterruptedException e){
e.printStackTrace();
}
this.content=content;
}
public synchronized void get(){
try{
Thread.sleep(100);
}catch (InterruptedException e){
e.printStackTrace();
}
System.out.println(this.title+"-->"+this.content);
}
}
class Producer2 implements Runnable{
private Message2 meg=null;
public Producer2(Message2 msg){
this.meg=msg;
}
@Override
public void run(){
for(int x=0;x<20;x++){
if(x%2==0){
this.meg.set("小关","学习Java");
}else{
this.meg.set("小梁","学习Python");
}
}
}
}
class Consumer2 implements Runnable{
private Message2 msg=null;
public Consumer2(Message2 msg){
this.msg=msg;
}
@Override
public void run(){
for (int x=0;x<20;x++){
this.msg.get();
}
}
}
public class Test11 {
public static void main(String []args)throws Exception{
Message2 msg=new Message2();
new Thread(new Producer2(msg)).start();
new Thread(new Consumer2(msg)).start();
}
}
//结果:
//小梁-->学习Python
//小梁-->学习Python
//小梁-->学习Python
//小梁-->学习Python
//(...)
The above procedure solves the problem of data misalignment, but there are still problems of repeated removal and repeated setting.
Resolve data duplication
Object class support for multithreading
No. | method | Types of | description |
---|---|---|---|
1 | public final void wait() throws InterruptedException | ordinary | Thread waiting |
2 | public final void notify() | ordinary | Wake up the first waiting thread |
3 | public final void notifyAll() | ordinary | Wake up all waiting threads |
In general, all waiting threads will be arranged in order.
If the notify () method is used, the first waiting thread will be woken up;
if the notifyAll () method is used, all the waiting threads will be woken up . Which thread has the highest priority will be executed first.
Example:
package Project.Study.Multithreading;
class Message3{
private String title;
private String content;
private boolean flag=true;
//flag==true:表示可以生产,但是不能拿走
//flag==false:表示可以取走,但是不能生产
public synchronized void set(String title,String content){
if(this.flag==false){
try {
super.wait(); //等待
}catch (InterruptedException e){
e.printStackTrace();
}
}
this.title=title;
try {
Thread.sleep(100);
}catch (InterruptedException e){
e.printStackTrace();
}
this.content=content;
this.flag=false; //已经生产完成,修改标志位
super.notify(); //唤醒等待线程
}
public synchronized void get(){
if (this.flag==true){ //未生产,不能取走
try {
super.wait(); //等待
}catch (InterruptedException e){
e.printStackTrace();
}
}
try {
Thread.sleep(100);
}catch (InterruptedException e){
e.printStackTrace();
}
System.out.println(this.title+"-->"+this.content);
this.flag=true; //已经取走了,可以继续生产
super.notify(); //唤醒等待线程
}
}
class Producer3 implements Runnable{
private Message3 meg;
public Producer3(Message3 msg){
this.meg=msg;
}
@Override
public void run(){
for(int x=0;x<10;x++){
if(x%2==0){
this.meg.set("小关","学习Java");
}else{
this.meg.set("小梁","学习Python");
}
}
}
}
class Consumer3 implements Runnable{
private Message3 msg;
public Consumer3(Message3 msg){
this.msg=msg;
}
@Override
public void run(){
for (int x=0;x<10;x++){
this.msg.get();
}
}
}
public class Test12 {
public static void main(String []args){
Message3 msg=new Message3();
new Thread(new Producer3(msg)).start();
new Thread(new Consumer3(msg)).start();
}
}
//结果:
//小关-->学习Java
//小梁-->学习Python
//小关-->学习Java
//小梁-->学习Python
//小关-->学习Java
//小梁-->学习Python
//小关-->学习Java
//小梁-->学习Python
//小关-->学习Java
//小梁-->学习Python
The above procedure solves the problems of data misalignment, repeated data removal and repeated setting.
Tip:
The difference between sleep () and wait ():
1.sleep () is a static method defined by the Thread class, which means that the thread sleeps and will give the execution opportunity to other threads, but the monitoring state is still maintained and will automatically resume;
2.wait ( ) Is a method defined by the Object class, which means that the thread waits until the notify () or notifyAll () is executed.