JAVA多线程总结

一、多线程的基本知识

1、创建一个线程的两个方法
  1. 通过继承Thread类本身。
  2. 通过实现Runnable接口;
  通过继承Thread类的方式有一定的局限性,java中只支持单一一个类,一旦继承了其他类就不能继承Thread类了。
----通过继承thread类创建线程

class MyThread extends Thread {   
    private int i = 0;
    public void run() {
        for (i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName() + " " + i);//获取线程名称;
        }
    }
}
public class ThreadTest {
    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName() + " " + i);
                Thread myThread1 = new MyThread();     // 创建一个新的线程  myThread1  此线程进入新建状态
                Thread myThread2 = new MyThread();     // 创建一个新的线程 myThread2 此线程进入新建状态
                myThread1.start();                     // 调用start()方法使得线程进入就绪状态
                myThread2.start();                     // 调用start()方法使得线程进入就绪状态
            
        }
    }
}

----通过实现Runnable接口创建线程

class MyRunnable implements Runnable {
    private int i = 0;
    public void run() {
        for (i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName() + " " + i);
        }
    }
}
public class ThreadTest {
    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName() + " " + i);
                Runnable myRunnable = new MyRunnable(); // 创建一个Runnable实现类的对象
                Thread thread1 = new Thread(myRunnable); // 将myRunnable作为Thread target创建新的线程
                Thread thread2 = new Thread(myRunnable);
                thread1.start(); // 调用start()方法使得线程进入就绪状态
                thread2.start();  
        }
    }
}

2、Thread类的一些重要方法
1public void start()
使该线程开始执行; Java  虚拟机调用该线程的 run 方法。
public void run()
如果该线程是使用独立的 Runnable 运行对象构造的,则调用该 Runnable 对象的 run 方法;否则,该方法不执行任何操作并返回。
public final void setName(String name)
改变线程名称,使之与参数 name 相同。
public final void setDaemon(boolean on)
将该线程标记为守护线程或用户线程。
public final void setPriority(int priority)
更改线程的优先级。
public final void join(long millisec)
等待该线程终止的时间最长为 millis 毫秒。
public void interrupt()
中断线程。
public final boolean isAlive()
测试线程是否处于活动状态。
currentThread()获取当前线程
getName()获取当前线程名字
测试线程是否处于活动状态。 上述方法是被Thread对象调用的。下面的方法是Thread类的静态方法。
public static void yield()
暂停当前正在执行的线程对象,并执行其他线程。
只有与当前线程优先级相同或者更高的线程才能获得执行机会。
public static void sleep(long millisec)
在指定的毫秒数内让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度程序精度和准确性的影响。
public static boolean holdsLock(Object x)
当且仅当当前线程在指定的对象上保持监视器锁时,才返回 true。
public static Thread currentThread()
返回对当前正在执行的线程对象的引用。
public static void dumpStack()
将当前线程的堆栈跟踪打印至标准错误流。

3、Thread类的构造方法
  • Thread(Runnable threadOb,String threadName);// threadOb 是一个实现Runnable 接口的类的实例,并且 threadName指定新线程的名字。
  • Thread();
  • Thread(Rannable target);
  • Thread(String name) ;//继承Thread类,并赋予名字;

4、设置线程的优先级
静态常量说明
static int MAX_PRIORITY           线程可以具有的最高优先级。相当于10
static int MIN_PRIORITY           线程可以具有的最低优先级。相当于1
static int NORM_PRIORITY           分配给线程的默认优先级。相当于5
5、线程的生命周期及状态转换


二、多线程的同步

1、线程的安全
     多线程的并发执行可以提高程序的效率,但当多个线程去访问同一个资源是,将会引发一些安全问题。
     例如:多个窗口的售票系统,可能会在同一个时间卖出了同一张票。

2、同步代码块

Object lock =new Object();
synchronized(lock){
}
lock是一个锁对象,默认情况下标志位为1,当线程执行同步代码块时会将锁对象的标志为置为0,阻止其他线程的调用。
等当前线程执行完同步代码快后,新线程才能进入执行代码块内的内容。

实例
public class ThreadEx3{
    public static void main(String[] args) {
        Teacher t = new Teacher();
        new Thread(t, "窗口1").start();
        new Thread(t, "窗口2").start();
        new Thread(t, "窗口3").start();
    }
}
class Teacher implements Runnable {
    private int notes = 80;
   Object lock =new Object();
    public void run() {
        while (true) {
            synchronized(lock){

             if (notes > 0) {
            try {
                Thread.sleep(10); // 经过的线程休眠10毫秒
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "---发出的票数"
                    + notes--);
        }//if
         }//while
        }//run()    
}//Runnable
       

3、同步方法

synchronized 返回值类型 方法名(){}
被synchronized修饰的方法在某一时刻只允许一个线程访问,其他的线程都会发生堵塞。

实例
public class ThreadEx3{
    public static void main(String[] args) {
        Teacher t = new Teacher();
        new Thread(t, "窗口1").start();
        new Thread(t, "窗口2").start();
        new Thread(t, "窗口3").start();
    }
}
class Teacher implements Runnable {
    private int notes = 80;
    public void run() {
        while (true) {
            dispatchNotes(); // 调用售票方法
            if (notes <= 0) {
                break;
            }
        }
    }
    private synchronized void dispatchNotes() {//同步方法
        if (notes > 0) {
            try {
                Thread.sleep(10); // 经过的线程休眠10毫秒
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "---发出的票数"
                    + notes--);
        }
    }
}



4、比较和弊端
     在同步方法中也有锁的存在,只是在同步方法中的锁不需要手动创建,这就在一点程度上保证了锁的唯一性,同步方法被所以线程共享。
    弊端:
          线程每次执行同步代码的时候都会判断所得状态,这回消耗大量的资源,效率低下。


三、多线程通信( 等待/通知机制 )
1、解决的问题
            轮询的条件的可见性问题。多个线程将会按照一定顺序流执行。
           所谓等待/通知机制,就是线程A在执行的时候,需要一个其他线程来提供的结果,但是其他线程还没有告诉他这个结果是什么,于是线程A开始等待,
当其他线程计算出结果之后就将结果通知给线程A,A线程唤醒,继续执行。

      
2、用到的方法
void wait()wait()方法使得当前线程必须要等待,等到另外一个线程调用notify()或者notifyAll()方法。
void notify()notify()方法会唤醒一个等待当前对象的锁的线程。
void notifyAll()唤醒此同步锁上调用wait()方法的所以线程
以上的三个方法的调用者都应是同步锁对象.





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值