java多线程
多线程是cpu操作的最小单元,通过多重线程调度算法如:FIFO()、时间片轮换、最短作业等,通俗来将用多线程就是将一件事分成若干个组成交给若干个线程处理,从而加快了处理速度
一、为什么要使用多线程
就一点:提高计算机CPU的利用率
二、线程的分类
分为主线程和子线程,main方法称之为主线程,其余的为子线程,子线程可细分为守护线程和非守护线程(其含义与守护进程和非守护进程相差不大)
public static void main(String[] args) {
new Thread(()->{
System.out.println("myThread");
//通过.setDaemon(true)将子线程设置为守护进程
}).setDaemon(true);
}
三、实现线程的方式
一、继承Thread
@SneakyThrows
public static void main(String[] args) {
Thread t1 = new myThread();
t1.setName("myThread");
t1.start();
}
// 继承Thread 创建线程
class myThread extends Thread{
@Override
public void run() {
System.out.println(Thread.currentThread().getName() +" Is Running ....");
}
}
二、实现Runnable
@SneakyThrows
public static void main(String[] args) {
myThread2 t2 = new myThread2();
t2.setName("myThread2");
t2.run();
}
//实现Runnable 创建线程
class myThread2 implements Runnable {
private String name;
public void setName(String name){
this.name = name;
}
@Override
public void run() {
Thread.currentThread().setName(name);
System.out.println(Thread.currentThread().getName() + " Is Running ....");
}
}
三、实现Callable
@SneakyThrows
public static void main(String[] args) {
//FutureTask 结果对象(下一篇再总结)
FutureTask<String> futureTask = new FutureTask<>(thread3);
new Thread(futureTask).start();
System.out.println(futureTask.get());
}
//实现Runnable 创建线程
class myThread3 implements Callable<String> {
@Override
public String call(){
return Thread.currentThread().getName() + " Is Running ....";
}
}
四、线程的状态
New(初始):新建状态,当线程创建完成时为新建状态,即new Thread(…),还没有调用start方法时,线程处于新建状态。
RUNNABLE(运行):在 Java 虚拟机中执行的线程处于这种状态。。
BLOCKED(阻塞):被阻塞等待监视器锁的线程处于这种状态
WAITING(等待):无限期等待另一个线程执行特定操作的线程处于此状态。
TIMED_WAITING(超时等待):等待另一个线程执行操作达指定等待时间的线程处于此状态。
TERMINATED(终止):已退出的线程处于此状态。
线程状态之间的切换
五、线程中常用的方法
/**
* 返回对当前正在执行的线程对象的引用
* 获取到线程对象之后进行操作
*/
public static native Thread currentThread();
/**
*调用该方法是放弃当前对cup的使用,一般是很少使用
*/
public static native void yield();
/**
* 使当前正在执行的线程休眠(暂时停止执行)参数为毫秒数,该线程不会失去任* * 何监视器的所有权(不会释放当前的锁)。
*/
public static native void sleep(long millis) throws InterruptedException;
/**
* 多了一个纳秒单位
*/
public static void sleep(long millis, int nanos)
throws InterruptedException {}
/**
* init基本是初始化的意思 使用AccessControlContext来初始化一个线程
*/
private void init(ThreadGroup g, Runnable target, String name,
long stackSize) {
init(g, target, name, stackSize, null, true);
}
/**
* 参数:
* g – 线程组
* target – 调用 run() 方法的对象
* name - 新线程的名称
* stackSize – 新线程所需的堆栈大小,或为零表示该参数将被忽略。
* acc – 要继承的 AccessControlContext,或者 AccessController.getContext() *如果为 null
* inheritThreadLocals – *如果为true,则从构造线程继承可继承线程局部变量的初始值
*/
private void init(ThreadGroup g, Runnable target, String name,
long stackSize, AccessControlContext acc,
boolean inheritThreadLocals) {}
/**
* 使该线程开始执行; Java虚拟机调用这个线程的run方法。
* 结果是两个线程并发运行:当前线程(从调用start方法返回)和另一个线程(执行**其run方法)。
* 多次启动一个线程是不合法的。 特别是,线程一旦完成执行就可能不会重新启动
*/
public synchronized void start() {}
/**
* 如果该线程是使用单独的Runnable运行对象构造的,则调用该Runnable对象的run方法**; 否则,此方法不执行任何操作并返回。
* Thread子类应该覆盖这个方法。
*/
public void run() {}
/**
* 该方法由系统调用,以在线程实际退出之前给它一个清理的机会
*/
private void exit() {}
/** 强制停止(不建议使用此操作)**/
public final void stop() {}
/**
* 中断此线程。
* 除非当前线程正在中断自己,这总是被允许的,否则调用此线程的checkAccess方法,这可能会导致抛出SecurityException 。
* 如果此线程在调用Object类的wait() 、 wait(long)或wait(long, int)方法或join() 、 join(long) 、 join(long, int)被阻塞、 sleep(long)或sleep(long, int) ,此类的方法,则其中断状态将被清除并收到InterruptedException 。
* 如果此线程在InterruptibleChannel的 I/O 操作中被阻塞,则通道将关闭,线程的中断状态将被设置,线程将收到java.nio.channels.ClosedByInterruptException 。
* 如果该线程在java.nio.channels.Selector被阻塞,则该线程的中断状态将被设置,并且它将立即从选择操作中返回,可能具有非零值,就像调用了选择器的wakeup方法一样。
* 如果前面的条件都不成立,则将设置此线程的中断状态。
* 中断一个不活跃的线程不需要有任何影响。
* 抛出:
* SecurityException – 如果当前线程不能修改这个线程
*/
public void interrupt() {}
/**
* 测试此线程是否已被中断。 线程的中断状态不受此方法的影响。
* 由于线程在中断时不处于活动状态而被忽略的线程中断将通过此方法返回 false 来反映。
* 返回:
* 如果此线程已被中断,则为true ; 否则为false
*/
public boolean isInterrupted() {}
/**
* 测试此线程是否存活。 如果线程已启动且尚未死亡,则该线程处于活动状态。
* 返回:
* 如果此线程还活着,则为true ; 否则为false
*/
public final native boolean isAlive(){};
/**
* 更改此线程的优先级。(默认层级是1-10,1是最高)
* 首先不带参数调用此线程的checkAccess方法。 这可能会导致抛出SecurityException 。
* 否则,该线程的优先级被设置为指定的newPriority和线程的线程组的最大允许优先级中的较小者。
*/
public final void setPriority(int newPriority){}
/** 获取该线程的优先级 */
public final int getPriority() {}
/** 将此线程的名称 */
public final synchronized void setName(String name) {}
/** 返回此线程的名称 */
public final String getName() {}
/** 返回该线程所属的线程组。 如果此线程已死亡(已停止),则此方法返回 null */
public final ThreadGroup getThreadGroup(){}
/**
* 返回当前线程的线程组及其子组中活动线程数的估计值。 递归迭代当前线程的线程组中的所有子组。
* 返回值只是一个估计值,因为该方法遍历内部数据结构时,线程数可能会动态变化,并且可能会受到某些系统线程存在的影响。 此方法主要用于调试和监视目的
*/
public static int activeCount() {}
/** 不传参数就是一直等待也等同于xxThread.join(0);
*源码中是调用了wait() 和 isalive
*/
public final synchronized void join(long millis,int nanos){}
/** 将当前线程的堆栈跟踪打印到标准错误流。 此方法仅用于调试 */
public static void dumpStack(){}
/** 返回此线程的上下文类加载器。 上下文 ClassLoader 由线程的创建者提供,供在该线程中运行的代码在加载类和资源时使用。 如果未设置,则默认为父线程的 ClassLoader *上下文。 原始线程的上下文类加载器通常设置为用于加载应用程序的类加载器
*/
public ClassLoader getContextClassLoader() {}
/**
* 返回表示此线程的堆栈转储的堆栈跟踪元素数组。 如果此线程尚未启动、已启动但尚未被系统安排运行或已终止,则此方法将返回一个零长度数组。
* 如果返回的数组长度不为零,则数组的第一个元素表示堆栈的顶部,这是序列中最近的方法调用。 数组的最后一个元素代表堆栈的底部,它是序列中最近的方法调用
* 如果存在安全管理器,并且该线程不是当前线程,则使用RuntimePermission("getStackTrace")权限调用安全管理器的checkPermission方法,以查看是否可以获取堆栈跟踪。
* 在某些情况下,某些虚拟机可能会从堆栈跟踪中省略一个或多个堆栈帧。 在极端情况下,允许没有与此线程相关的堆栈跟踪信息的虚拟机从此方法返回零长度数组。
*/
public StackTraceElement[] getStackTrace() {}