1、线程同步:当有一个线程在对内存进行操作时,其他线程都不可以对这个内存地址进行操作,直到该线程完成操作, 其他线程才能对该内存地址进行操作,而其他线程又处于等待状态。如果线程不同步,即在不同线程同时访问同一资源的过程中就会出现问题。
2、线程同步处理——关键是“锁”
使用synchronized关键字实现线程同步。在同步代码块中的代码每次仅允许一个线程执行。
利用同步代码块解决:
class MyThread implements Runnable {
private int ticket = 5;
@Override
public void run() {
while(true) {
synchronized(this) { //每次仅允许一个线程进行访问,“同步对象”参数,一般都选用当前线程对象this
if(this.ticket > 0) {
try {
Thread.sleep(100); //暂缓执行
}catch(InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() +"," + this.ticket --);
}else {
System.out.println("结束");
break;
}
}
}
}
}
public class Demo {
public static void main(String[] args) throws Exception {
MyThread mt = new MyThread() ;
new Thread(mt, "线程A").start();
new Thread(mt, "线程B").start();
new Thread(mt, "线程C").start();
}
}
加入同步处理之后,程序的整体性能有所下降。
利用同步方法解决:
class MyThread implements Runnable {
private int ticket = 5;
public synchronized boolean sale() {
if(this.ticket > 0) {
try {
Thread.sleep(100); //暂缓执行
}catch(InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() +"," + this.ticket --);
return true;
}else {
System.out.println("结束");
return false;
}
}
@Override
public void run() {
while(this.sale()) {
;
}
}
}
3、线程死锁
造成死锁的主要原因在于线程之间在互相等待,等待对方让出资源。若干个线程访问同一资源时一定要进行同步处理,而过多的同步会造成死锁。
5、利用Object类解决重复操作
死等:public final void wait() throws InterruptedException
设置等待时间:public final void wait(long timeout) throws InterruptedException
设置等待时间:public final void wait(long timeout,int nanos) throws InterruptedException
唤醒第一个等待线程:public final void notify();
唤醒全部等待线程:public final void notifyAll();
4、【生产者与消费者模型】
// 生产者与消费者模型
//生产者
class Producer implements Runnable {
private Message1 msg ;
public Producer(Message1 msg) {
this.msg = msg ;
}
@Override
public void run() {
for(int x = 0 ; x < 6 ; x ++) {
if(x % 2 == 0) {
this.msg.set("标题一","内容一");
}else {
this.msg.set("标题二","内容二");
}
}
}
}
// 消费者
class Consumer implements Runnable {
private Message1 msg ;
public Consumer(Message1 msg) {
this.msg = msg ;
}
@Override
public void run() {
for(int x = 0 ; x < 5 ; x ++) {
System.out.println(this.msg.get());
}
}
}
//将同步处理交由Message完成(生产和消费的对象)
class Message1 {
private String title;
private String content;
private boolean flag = true ; //表示生产和消费的形式,flag=true,允许生产但是不允许消费,避免一次生产多次消费等状况
//同步处理后多个线程不能同时访问同一资源,通俗来讲,生产者在生产第一个产品时(mag.title和msg.content),不允许开始生产第二个
public synchronized void set(String title, String content) {
if(!this.flag) { //无法进行生产,应该等待被消费
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 String get() {
if(this.flag == true) { //还未生产,需要等待
try {
super.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
try {
Thread.sleep(100);
}catch(InterruptedException e) {
e.printStackTrace();
}
try {
return this.title + "-" + this.content ;
}finally {
this.flag = true ; //继续生产
super.notify(); //唤醒等待线程
}
}
}
public class Pool {
public static void main(String[] args) throws Exception {
Message1 msg = new Message1() ;
new Thread(new Producer(msg)).start(); //启动生产者线程
new Thread(new Consumer(msg)).start(); //启动消费者延迟
}
}
通过同步处理与解决重复操作,此时刚好是:生产一个完整产品消费一个完整产品