欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java多线程---线程、同步

程序员文章站 2022-05-04 18:17:31
...

Java多线程

线程和进程的区别

可能也就是一个选择题

线程

在于并发concurrent

线程的生命周期
Java多线程---线程、同步
看图就好了

创建Java线程的方式

通过继承Thread方式实现

1.新建一个类,继承Thread类,这里叫作MyThread
2.完善run方法();执行代码在这里
3.新建MyThread实例
4.start()

   class MyThread extends Thread       //自定义线程类
        {
            public void run()                       //核心方法
            {
                System.out.println("MyThread线程执行");
            }
        }
public  class test
        {
            public static void main(String []args)
            {
                    MyThread myThread=new MyThread();        //创建实例
                    myThread.start();                  //一定要用start,不可用run
            }

通过实现Runnable接口

1.新建一个类,实现Runnable接口
2.重点在于实现run方法。
3.新建一个Runnable类实例
4.新建一个Thread类实例,初始化时传入实现了Runnable的类实例
5.start()

     ....
        {
            public static void main(String []args)
            {
                    MyThread myThread=new MyThread();
                    Thread thread=new Thread(myThread);         //将实现了Runnable的接口的类实例传过去
                    thread.start();
            }
        }

class MyThread implements Runnable          //实现了Runnable接口
{
    public void run()
    {
        System.out.println("线程运行");
    }
}

几个跟线程生命周期相关的方法

yield:当前线程让出,当前线程进入就绪状态,等候重新获取
sleep:当前线程睡眠一段时间,进入阻塞状态,时间到了之后进入就绪状态
join:强制插入,使线程成为运行状态

重点:线程同步

PPT主要讲了synchronized方法。

synchronized

使用方法:
sychronized锁住某段代码块
sychronized锁住某个方法
通过对互斥锁的获取和释放,保证了只有一个线程拥有锁,
只有拥有锁的线程才能执行对应的程序
每个对象都可以作为互斥锁
一般用当前对象

程序执行完会自动释放锁

synchronized(Object )           //同步代码块
{
 }

 public synchronized int getNum()     //同步方法,默认用当前类的实例对象作为锁
 {
 }

线程通信

wait
notify
notifyall
这个比较重实践

总结一下多线程的题目:
1.确定共享变量,尽可能的少 而足
2.定义共享变量(一些状态变量、一些锁)
3.定义一个实现了Runnable的类模板
4.通过参数设置不同的类实例(eg:abc、次数、下一个state)
5.开始start

**可以通过改变state,指定下一个code实现指定的任务启动**

实践

public class test {
   public static volatile int state=0;        //通过类的静态变量实现变量共享、并且是唯一变量

   class printer implements Runnable
   {     //内部类。主要是为了实现
       private int printcode;
       private int nextCode;                   //用于指示下一个状态量
       private Object printLock;            //锁元素
       private int countNum;
       private char printchar;

       public printer(Object printLock, int countNum, int printcode, int nextCode, char printchar)        //通过传入参数,实现不同实例要求
       {
           this.printchar = printchar;
           this.printcode = printcode;
           this.printLock = printLock;
           this.countNum = countNum;
           this.nextCode = nextCode;
       }

       public void run() {        //运行方法
           synchronized (printLock) {         //同步代码段
               for (int i = 0; i < countNum; i++) {

                   try {
                       if (printcode != test.state) {
                           printLock.wait();
                       }
                       else{
                           System.out.println(printchar);
                           test.state = nextCode;
                           printLock.notifyAll();              //一定要是notifyall
                       }
                   } catch (InterruptedException e) {
                       return;
                   }

               }
           }
       }   //内部类结束,内部类是为了能够简单的直接获取state共享变量
   }
   public void tst()
   {
       Object lock=new Object();
       printer pa=new printer(lock,20,0,1,'a');      //各自的实例
       printer pb=new printer(lock,20,1,2,'b');
       printer pc=new printer(lock,20,2,0,'c');
       Thread m1=new Thread(pa);
       Thread m2=new Thread(pb);
       Thread m3=new Thread(pc);
       m1.start();
       m2.start();
       m3.start();
   }

   public static void main(String[]args)            //外部类的main方法
   {
  test t=new test();
  t.tst();
   }
}

另外的一种实现方式是Java的锁lock
ReentrantLock和condition
不建议这么用 ,万一被老师判错
ReentrantLock是一个锁,可以实现跟 synchronized一样的*代码段的效果,
需要自己调用lock、unlock加锁解锁

ReentrantLock

方法:
lock() 加锁
unlock()解锁
newCondition() 通过锁产生条件,可以产生有多个条件

Condition

await() 等待,进入阻塞
sinal 通知一个线程解睡眠
sinalAll 通知所有线程解睡眠

// wait 模板,signal 模板
lock.lock();
try{
    // wait 条件:一般都是使用while
    while(meet the condition){
        condition.await();
    }
    // 满足条件进行一系列操作
    ... your operation
    otherCondition.signal()// otherCondition.signalAll()

}catch(){

}finally{
    lock.unlock();
}

好吧,下面代码冗余太多了

import java.io.FileOutputStream;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public  class test
{
    public static void main(String[]args) throws  Exception
    {
        myThreaA a=new myThreaA();
        myThreaB b=new myThreaB();
        myThreaC c=new myThreaC();
        a.start();
        b.start();
        c.start();
    }
}

class Printer
{
    static ReentrantLock lock=new ReentrantLock();         //共享量
    static Condition c1=lock.newCondition();
    static Condition c2=lock.newCondition();
    static Condition c3=lock.newCondition();
    private static volatile int state=0;         //打印机状态
    private int  nowState;                     //实例的编号
    private char nowChar;                     //对应实例的打印内容
    Printer(int State,char c)
    {
        this.nowChar=c;
        this.nowState=State;
    }
    public void printA() throws InterruptedException
    {
        lock.lock();
        if (state!=nowState)
            c1.await();
        System.out.print('a');
        state=(state+1)%3;
        c2.signal();
        lock.unlock();
    }
    public void printC() throws InterruptedException
    {
        lock.lock();
        if (state!=nowState)
            c3.await();
        System.out.println('c');
        state=(state+1)%3;
        c1.signal();
        lock.unlock();
    }
    public void printB() throws InterruptedException
    {
        lock.lock();
        if (state!=nowState)
            c2.await();
        System.out.print('b');
        state=(state+1)%3;
        c3.signal();
        lock.unlock();
    }
}

class myThreaA extends Thread
{
    Printer a=new Printer(0,'a');
    public void run() {
        for (int i = 0; i < 20; i++) {
            try {
                a.printA();
            } catch (InterruptedException e) {
                return;
            }
        }
    }
}
class myThreaB extends Thread
{
    Printer b=new Printer(1,'b');
    public void run() {
        for (int i = 0; i < 20; i++) {
            try {
                b.printB();
            } catch (InterruptedException e) {
                return;
            }
        }
    }
}
class myThreaC extends Thread
{
    Printer b=new Printer(2,'c');
    public void run() {
        for (int i = 0; i < 20; i++) {
            try {
                b.printC();
            } catch (InterruptedException e) {
                return;
            }
        }
    }
}