实现线程的两种方式
在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,这篇就到这里了,希望大家喜欢。