java多线程技能基础

实现线程的两种方式

在java中实现线程有两种方式

  • 继承自Thread.java类
  • 实现Runnable.java接口
@FunctionalInterface
public interface Runnable {
    public abstract void run();
}

public
class Thread implements Runnable

可以看到Thread类实现了Runnable接口,由于java不支持多继承,所以如果有需要继承自其它类,则可以通过实现Runnable接口来实现多线程。

public class MyThread extends Thread {

    @Override
    public void run() {
        super.run();
        System.out.println("This is MyThread");
    }


    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        myThread.start();//只有调用start方法以后,该线程才真正执行

        System.out.println("This is Main");
    }
}

此时,打印如下:
这里写图片描述
从结果可以看出,使用多线程时候,代码的运行结果与代码的执行顺序或者调用顺序是没有关系的。

线程的随机性

public class RandomThread implements Runnable {

    private String mThreadName;



    public RandomThread(String mThreadName) {
        super();
        this.mThreadName = mThreadName;
    }

    @Override
    public void run() {
        System.out.println(mThreadName+"   runs....");
    }

    public static void main(String[] args) {
        new Thread(new RandomThread("rT1")).start();
        new Thread(new RandomThread("rT2")).start();
        new Thread(new RandomThread("rT3")).start();
        new Thread(new RandomThread("rT4")).start();
        new Thread(new RandomThread("rT5")).start();
        new Thread(new RandomThread("rT6")).start();
        new Thread(new RandomThread("rT7")).start();
        new Thread(new RandomThread("rT8")).start();
        new Thread(new RandomThread("rT9")).start();
        new Thread(new RandomThread("rT10")).start();
    }

}

程序运行的结果如下:
这里写图片描述
这里可以看出:执行start()方法的顺序,并不代表线程的启动顺序。

实例变量和线程安全

自定义线程中类中,有时候会包含实例变量,该变量对于其他线程,可以共享也可以不同享,这一点对于多线程交互时候尤为重要。

多线程不共享数据

public class NotShareThread extends Thread {

    private int count = 4;

    public NotShareThread(String threadName) {
        this.setName(threadName); //设置当前线程的名称
    }

    @Override
    public void run() {
        super.run();
        while (count > 0) {
            count--;
            System.out.println(Thread.currentThread().getName()+" count is :"+count);
        }
    }

    public static void main(String[] args) {
        NotShareThread nsT1 = new NotShareThread("Not share first");
        NotShareThread nsT2 = new NotShareThread("Not share second");
        NotShareThread nsT3 = new NotShareThread("Not share third");

        nsT1.start();
        nsT2.start();
        nsT3.start();
    }
}

这里写图片描述

多线程共享数据

public class ShareThread extends Thread {

    private int count = 4;

    @Override
    public void run() {
        super.run();
        count--;
        System.out.println(Thread.currentThread().getName()+" count is :"+count);
    }

    public static void main(String[] args) {
        ShareThread shareThread = new ShareThread();

        Thread sT1 = new Thread(shareThread, "share first");
        Thread sT2 = new Thread(shareThread, "share second");
        Thread sT3 = new Thread(shareThread, "share third");

        sT1.start();
        sT2.start();
        sT3.start();
    }
}

此时打印结果如下:
这里写图片描述
可以看到当前’second’,’first’线程打印count值都是2,这说明这两个线程同时对count进行处理,这就产生了”非线程安全”问题。其实解决该问题,我们只需要在run方法前添加一个”synchronized”关键字,使多个线程在执行run方法时候,以排队的方式进行处理。

@Override
    synchronized public void run() {
        super.run();
        count--;
        System.out.println(Thread.currentThread().getName()+" count is :"+count);
    }

这里写图片描述
当一个线程需要执行同步块中的方法时候,线程会首先尝试获取这把锁,如果获取锁成功,则执行synchronized里面的代码,否则不断尝试获取该锁。

线程常用方法

// 返回代码段正在被那个线程调用的信息
public static native Thread currentThread()
// 判断当前线程是否处于活动状态
public final native boolean isAlive();
// 让当前线程,休眠指定毫秒数
public static native void sleep(long millis) throws InterruptedException;
// 取得线程的唯一标识
public long getId() {
    return tid;
} 

// 测试当前线程是否已经是中断状态,执行后具有将状态标志清除为false的功能
public void interrupt() 

// 测试当前线程Thread对象是否已经是中断状态,但不清除状态标志
public boolean isInterrupted()

yield方法

// 放弃当前cpu资源,让给其他任务占用cpu时间,但是放弃的时间不确定,有可能刚刚放弃,立马又获得了cpu时间片
public static native void yield();
public class YieldThread extends Thread {

    @Override
    public void run() {
        super.run();
        int count = 0;
        long beginTime = System.currentTimeMillis();
        for (int i = 0; i < 555555555; i++) {
//          Thread.yield();
            count += i + 1;
        }
        long endTime = System.currentTimeMillis();
        System.out.println("it takes "+(endTime - beginTime)+"  ms");
    }

    public static void main(String[] args) {
        new YieldThread().start();
    }
}

程序运行结果如下:
这里写图片描述
此时去掉注释”// Thread.yield();”,执行结果如下:
这里写图片描述

抛异常停止线程

public class StopThread extends Thread {

    @Override
    public void run() {
        super.run();

        try {
            for (int i = 0; i < 5000000; i++) {
                if (this.isInterrupted()) { //判断当前线程是否被终止
                    System.out.println("我被终止了....");
                    // 抛出异常实现线程终止,在catch块中可以将异常继续向上抛
                    throw new InterruptedException();
                }
                System.out.println("current i is :"+i);
            }
            System.out.println("for 循环外边......");
        } catch (Exception e) {
            System.out.println("StopThread catch......");
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        try {
            StopThread stopThread = new StopThread();
            stopThread.start();

            Thread.sleep(2000);
            // 通过interrupt()方法,停止当前线程
            stopThread.interrupt(); 
        } catch (Exception e) {
            System.out.println("main catch......");
            e.printStackTrace();
        }
    }
}

这里写图片描述

线程的优先级

线程可以划分优先级,优先级较高的线程得到的CPU较多。可以通过

public final void setPriority(int newPriority)

设置当前线程的优先级

    /**
     * The minimum priority that a thread can have.
     */
    public final static int MIN_PRIORITY = 1;

   /**
     * The default priority that is assigned to a thread.
     */
    public final static int NORM_PRIORITY = 5;

    /**
     * The maximum priority that a thread can have.
     */
    public final static int MAX_PRIORITY = 10;

可以看到在java中线程的优先级分为1~10.

优先级的继承特性

线程的优先级具有继承特性,比如:A启动B线程,则B和A线程具有相同的优先级

public class ThreadA extends Thread {
    @Override
    public void run() {
        super.run();
        System.out.println("this is ThreadA ,proprity is :"+this.getPriority());
        ThreadB threadB = new ThreadB();
        threadB.start();
    }
}

// ==================================================
public class ThreadB extends Thread {
    @Override
    public void run() {
        super.run();
        System.out.println("this is ThreadB ,proprity is :"+this.getPriority());
    }
}

// ==================================================
public class ExtendThread {

    public static void main(String[] args) {
        System.out.println("this is main begin ,proprity is :"+Thread.currentThread().getPriority());
//      Thread.currentThread().setPriority(7);
        ThreadA threadA = new ThreadA();
        threadA.start();
        System.out.println("this is main end,proprity is :"+Thread.currentThread().getPriority());
    }
}

这里写图片描述
此时,在将上面main方法中的注释去掉,结果如下:
这里写图片描述

PS:高优先级的线程总是大部分先执行完,但是不一定高优先级的线程全部执行完成,另外线程的由下级与代码执行顺序无关。

优先级的随机性

public class ThreadA extends Thread {
    @Override
    public void run() {
        super.run();
        System.out.println("this is ThreadA ................");
    }
}
// ===============================================
public class ThreadB extends Thread {
    @Override
    public void run() {
        super.run();
        System.out.println("this is ThreadB =============");
    }
}

// ===============================================
public class RandomPriorityThread {

    public static void main(String[] args) {

        for (int i = 0; i < 5; i++) {
            ThreadA threadA = new ThreadA();
            threadA.setPriority(6);

            ThreadB threadB = new ThreadB();
            threadB.setPriority(5);
            threadA.start();
            threadB.start();
        }   
    }
}

这里写图片描述

守护线程

任何一个守护线程都是非守护线程的保姆,如果当前JVM中存在一个非守护线程没有结束,则守护线程就在工作,只有当最后一个非守护线程退出时,守护线程才结束工作。

public class DaemonThread extends Thread {

    @Override
    public void run() {
        int count = 0;
        while (true) {
            try {
                System.out.println("count is :"+count++);
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        System.out.println("main thread is start.....");
        DaemonThread daemonThread = new DaemonThread();
        // 设置daemonThread为守护线程
        daemonThread.setDaemon(true);
        daemonThread.start();
        // 5秒以后,main线程退出,此时没有任何非守护线程在执行,则守护线程自动结束
        Thread.sleep(5000);
    }
}

此时运行效果如下:
这里写图片描述

ok,这篇就到这里了,希望大家喜欢。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值