Cas d'opération classique entre le producteur de threads et le cas du consommateur
Modèle de programme de base:
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
//(...)
À l'origine, la sortie attendue du programme est: Xiaoguan-> apprentissage Java, Xiaoliang-> apprentissage python,
mais il y a évidemment un problème, les données définies sont mal alignées, les données sont extraites et définies à plusieurs reprises.
Résoudre le problème du trouble des données
Le désalignement des données est entièrement dû aux opérations asynchrones, donc le traitement synchrone doit être utilisé.
Exemple: Rejoignez la synchronisation pour résoudre le problème de trouble des données
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
//(...)
La procédure ci-dessus résout le problème de désalignement des données, mais il y a toujours des problèmes de suppression et de réglage répétés.
Résoudre la duplication des données
Prise en charge des classes d'objets pour le multithreading
Non. | La méthode | Tapez | La description |
---|---|---|---|
1 | public final void wait () lève InterruptedException | Ordinaire | Attente du fil |
2 | annulation finale publique notifier () | Ordinaire | Réveillez le premier fil d'attente |
3 | annulation finale publique notifierAll () | Ordinaire | Réveillez tous les threads en attente |
En général, tous les threads en attente seront classés dans l'ordre.
Si la méthode notify () est utilisée, le premier thread en attente sera réveillé;
si la méthode notifyAll () est utilisée, tous les threads en attente seront réveillés . Le thread qui a la priorité la plus élevée sera exécuté en premier.
Exemple:
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
La procédure ci-dessus résout les problèmes de désalignement des données, de suppression de données répétée et de réglage répété.
Astuce:
SLEEP () et attente () la différence:
1.sleep () est une méthode statique de la définition de la classe de fil, indique que le fil de dormir, la possibilité d'exécuter un autre thread, mais la surveillance reste d'état, reprendra automatiquement;
2.Wait ( ) Est une méthode définie par la classe Object, ce qui signifie que le thread attend l'exécution de notify () ou notifyAll ().