1、进程与线程
进程:操作系统中程序的一次执行过程,是操作系统资源分配的最小单元
线程:进程的一个子任务,是操作系统任务分配的最小单元,在一个进程中所有的线程共享进程资源
进程与线程的关系:
1、进程是操作系统资源分配的最小单元,线程是操作系统任务分配的最小单元
2、进程的启动与销毁开销较大,与此相比,启动与销毁一个线程,开销要小的多
3、进程间通信远比线程间通信小的多
高并发:在同一时刻,并发访问的线程数量非常高
高可用:若干个服务器坏了不会导致整个程序的瘫痪,(程序部署在多台服务器上)
分布式:一个程序同时部署在多台机器上
java 启动一个JVM进程
main方法是主线程
2、java多线程的实现
java.lang.Thread类是java中多线程的核心类
无论使用哪种方式创建线程,启动线程一律使用Thread类提供的Start()方法而不用run()方法,run()方法不能通过用户直接调用
(使用run的话就是串行执行而不是并行执行),并且,任何一个线程的Start( )方法只能被执行一次,不能重复调度,执行多次会抛出IllegalThreadStateException
package com.wfg.xc;
/**
* @Author: WFG
* @Date: 2019/8/29 14:53
* @Description:
*/
class MyThread extends Thread{
private String title;
public MyThread(String title) {
this.title = title;
}
@Override
//此方法为每个线程都需要执行的任务
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("当前的线程为"+title+i);
}
}
}
public class ThreadTest {
public static void main(String[]args){
MyThread mt1 = new MyThread("子线程1,");
MyThread mt2 = new MyThread("子线程2,");
MyThread mt3 = new MyThread("子线程3,");
mt1.run();
mt2.run();
mt3.run();
}
}
结果:
修改:
public class ThreadTest {
public static void main(String[]args){
MyThread mt1 = new MyThread("子线程1,");
MyThread mt2 = new MyThread("子线程2,");
MyThread mt3 = new MyThread("子线程3,");
mt1.start();
mt2.start();
mt3.start();
}
}
结果:
创建多线程的方法:
1、继承Thread类,然后覆写run方法(线程任务)2、实现Runnable接口,而后覆写run()方法
java中Thread类本身也实现了Runnable接口,与用户自定义的线程类共同组成代理设计模式。其中,Thread类实现辅助操作,包括线程的资源调度等任务;自定义类线程类实现真实业务。
继承Thread类和Runnable区别:
(1)继承Thread类有单继承局限,相对而言,Runnable接口更加灵活,,而且Thread类本身也实现了Runnable辅助真实线程类
(2)实现Runnable接口可以更好的实现程序共享的概念,(Thread类也可以,稍微麻烦一点)
3、实现Callable接口,而后覆写call<V>方法
V call() throws Exception; 线程执行任务后有返回值!如果要求线程执行完后返回一个值,只能采用此方法
Future接口接收Callable接口的返回值
V get() 方法接收返回值
//第一步:产生Callable对象 CallableThread callableThread = new CallableThread(); //第二步:产生FutureTask对象,接收Callable对象 FutureTask<String> futureTask = new FutureTask<>(callableThread); //第三步:将futureTask对象传入Thread Thread thread = new Thread(futureTask); thread.start();
4、线程池
常用的线程操作方法
取得当前JVM中正在执行的线程对象
public static native Thread currentThread();
1、线程名称的命名与取得
线程命名:
public Thread(Runnable target,String name)
public final synchronized void setName(String name)
线程名称取得:
String getName( )
2、线程休眠 sleep(long time)单位为毫秒
线程休眠指的是让线程暂缓执行以下,等到了预计时间之后再恢复执行
sleep方法会让当前线程立即交出CPU,但不会释放对象锁。
3、线程让步 yield()方法
暂停当前正在执行的线程对象,并执行其他线程(只能让拥有相同优先级的线程获取CPU)。
当前线程不会立即交出CPU,交出时间由系统调度。
同样不会释放对象锁
4、线程等待,join()方法
若一个线程1需要等待线程2执行完毕后再恢复执行,可以在线程1中调用线程2的join( )方法。(在哪个线程中调用,哪个线程阻塞,等待线程执行完毕载恢复执行)
线程停止:
1、设置标志位(无法处理阻塞时停止的问题)
package com.wfg.method; /** * @Author: WFG * @Date: 2019/8/29 17:41 * @Description: 线程停止方式一:设置标志位 */ class ThreadShutDown implements Runnable{ private boolean flag = true; public void setFlag(boolean flag) { this.flag = flag; } @Override public void run() { int i = 0; while (flag) { System.out.println(Thread.currentThread().getName() +","+i++); } System.out.println("线程停止"); } } public class ThreadStop { public static void main(String[]args) throws InterruptedException { ThreadShutDown threadShutDown = new ThreadShutDown(); Thread thread = new Thread(threadShutDown); thread.start(); Thread.sleep(1000);//主线程休眠一秒,在哪个线程调用哪个休眠 threadShutDown.setFlag(false); } }
2、调用Thread类提供stop方法强行关闭线程。本方法现在已经不推荐使用,会产生不完整数据
public class ThreadStop { public static void main(String[]args) throws InterruptedException { ThreadShutDown threadShutDown = new ThreadShutDown(); Thread thread = new Thread(threadShutDown); thread.start(); Thread.sleep(1000);//主线程休眠一秒,在哪个线程调用哪个休眠 thread.stop(); } }
3、通过调用Thread类提供的interrupt()方法
第一种情况:若线程中没有使用类似sleep/wait/join将线程阻塞时,调用此线程对象的interrupt方法并不会真正中断线程,只是简单的将线程的状态置为interrupt(中断状态)而已,我们可以根据此状态进一步确定如何处理线程。
Thread类提供的public boolean isInterrupted( )可以检测当前线程状态是否为中断状态。
package com.wfg.method; /** * @Author: WFG * @Date: 2019/8/29 17:41 * @Description: 线程停止方式一:设置标志位 */ class ThreadShutDown implements Runnable{ private boolean flag = true; public void setFlag(boolean flag) { this.flag = flag; } @Override public void run() { int i = 0; while (flag) { /*boolean bool = Thread.currentThread().isInterrupted(); if (bool) { System.out.println("线程已被置为中断状态"); return; } System.out.println("当前线程的状态为:"+bool);*/ System.out.println(Thread.currentThread().getName() +","+i++); } System.out.println("线程停止"); } } public class ThreadStop { public static void main(String[]args) throws InterruptedException { ThreadShutDown threadShutDown = new ThreadShutDown(); Thread thread = new Thread(threadShutDown); thread.start(); Thread.sleep(1000);//主线程休眠一秒,在哪个线程调用哪个休眠 thread.interrupt(); } }
第二种情况:若线程中调用了阻塞线程的方法如:sleep(),wait(),join()此时再调用线程的interrupt方法时会抛出异常InterruptedException(中断异常),同时将线程状态还原(isInterrupted =false)
package com.wfg.method; /** * @Author: WFG * @Date: 2019/8/29 17:41 * @Description: 线程停止方式一:设置标志位 */ class ThreadShutDown implements Runnable{ private boolean flag = true; public void setFlag(boolean flag) { this.flag = flag; } @Override public void run() { int i = 0; while (flag) { try { Thread.sleep(200); boolean bool = Thread.currentThread().isInterrupted(); if (bool) { System.out.println("线程已被置为中断状态"); return; } System.out.println("当前线程的状态为:"+bool); System.out.println(Thread.currentThread().getName() +","+i++); } catch (InterruptedException e) { boolean bool = Thread.currentThread().isInterrupted(); if (bool) { System.out.println("线程已被置为中断状态"); return; } System.out.println("当前线程的状态为:"+bool); System.out.println(Thread.currentThread().getName() +","+i++); e.printStackTrace(); } } System.out.println("线程停止"); } } public class ThreadStop { public static void main(String[]args) throws InterruptedException { ThreadShutDown threadShutDown = new ThreadShutDown(); Thread thread = new Thread(threadShutDown); thread.start(); Thread.sleep(1000);//主线程休眠一秒,在哪个线程调用哪个休眠 thread.interrupt(); } }
线程优先级:
线程的优先级指的是优先级越高越有可能先被执行而已。
设置优先级setPriority (int priority)
取得优先级int getPriority()
public class TestPriority { public static void main(String[]args){ System.out.println(Thread.currentThread().getPriority()); } }
JDK设置了三种优先级:
MAX_PRIORITY =10;
NORM_PRIORITY = 5;
MIN_PRIORITY = 1;
class PriThread implements Runnable{ @Override public void run() { for (int i = 0; i < 3; i++) { System.out.println(Thread.currentThread().getName()+",i = "+i); } } } public class TestPriority { public static void main(String[]args){ PriThread priThread = new PriThread(); Thread th1 = new Thread(priThread); Thread th2 = new Thread(priThread); Thread th3 = new Thread(priThread); th1.setPriority(Thread.MAX_PRIORITY); th2.setPriority(Thread.NORM_PRIORITY); th3.setPriority(Thread.MIN_PRIORITY); th1.start(); th2.start(); th3.start(); } }
线程的继承性:
若在一个线程中创建了子线程,默认子线程与父线程的优先级相同
class PriThread implements Runnable{ @Override public void run() { System.out.println(Thread.currentThread().getName()+ ",优先级为"+Thread.currentThread().getPriority()); new Thread(new PriThread(),"孙子线程B").start(); } } public class TestPriority { public static void main(String[]args){ PriThread priThread = new PriThread(); Thread thread = new Thread(priThread,"子线程A"); thread.setPriority(10); thread.start(); } }
守护线程DaemonThread:
java中线程分为两类:用户线程,守护线程
守护线程为陪伴线程,只要JVM中存在任何一个用户线程没有终止,守护线程就一直在工作。
默认创建的线程都是用户线程,包括主线程
通过Thread类的setDaemon(true)方法将线程对象设置为守护线程
class DaemonTest implements Runnable{ @Override public void run() { while (true) { System.out.println("当前线程是否为守护线程"+ Thread.currentThread().isDaemon()); try { Thread.sleep(1000); } catch (InterruptedException e) { System.out.println("当前线程是否为守护线程"+ Thread.currentThread().isDaemon()); System.out.println("线程被中止"); return; } } } } public class DaemonThread { public static void main(String[]args) throws InterruptedException { DaemonTest daemonTest = new DaemonTest(); Thread thread1 = new Thread(daemonTest); Thread thread2 = new Thread(daemonTest); thread1.setDaemon(true); thread1.start(); thread2.start(); Thread.sleep(3000); //中断th2 thread2.interrupt(); Thread.sleep(5000); System.out.println("代码结束..."); } }
典型的守护线程:垃圾回收线程