什么是多线程:
多线程顾名思义就是有多个线程在执行任务,就像小龙女左手画圆,右手画正方形一样。它实在
CPU的调度下来回切换的,但是因为人的视觉感官的问题,觉得在同时执行的。
多线程的意义:
可以充分利用CPU资源,在一个线程被执行的时候,多余出来的CPU资源,可以分配给其他的线
程来执行。
程序 进程 线程:
程序:是一个静态概念,电脑上未曾运行时的应用都算,比如qq,浏览器等;学术化一些的说法
有,可以执行的静态文件;其实我们可以看到安装的程序都是由一堆文件组成;
进程:系统分配资源的最小单位;程序的一次动态执行过程;一个程序可以有多个进程,一个进程
必定只属于一个程序;进程可以被系统划分好独立的地址;进程之间的内存空间互不干扰;
线程:线程是最小的执行单元,同一个进程有多个线程,同一个进程内的线程共享同个内存空间,
而且有的线程之间相互依赖;
实现线程的方法:
继承Thread类,重写Run方法
public class thread extends Thread {
@Override
public void run() {
for (char i = 'A'; i <'z'; i++) {
String threadName = currentThread().getName();
System.out.println("thread:"+i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
实现Runable接口,重写Run方法
public class rubthread implements Runnable{
@Override
public void run() {
for (int i = 0; i <= 10000; i++) {
String threadName = thread.currentThread().getName();
System.out.println(threadName+":"+i);
}
}
}
实现Callable接口,实现call方法
public class callThread implements Callable<String> {
String str = new String();
@Override
public String call() throws Exception {
for (int i = 0; i <= 10000; i++) {
String threadName = thread.currentThread().getName();
System.out.println(threadName + ":" + i);
str = str + i;
}
return str;
}
}
值得注意的是,与Runable相比,callable多了返回值
通过Exexutor的工具创建线程池,通过线程池获取线程:
public class Pool {
public static void main(String[] args) {
// 创建=线程池
ExecutorService pool = Executors.newFixedThreadPool(10);
// 提交一个逻辑处理对象,线程池分配一个空闲线程
pool.execute(new rubthread());
pool.execute(new rubthread());
while (true) {
pool.execute(new Runnable() {
@Override
public void run() {
System.out.println("创建线程:" + Thread.currentThread().getName());
try {
thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
}
}
这些就是线程的创建方法
因为线程是由JVM调度的,我们没法准确控制谁先谁后,但是在Thread中的可以影响线程的执行
Sleep方法:
使线程按我们指定的时间来进行休眠
public class Pool {
public static void main(String[] args) {
// 创建=线程池
ExecutorService pool = Executors.newFixedThreadPool(10);
// 提交一个逻辑处理对象,线程池分配一个空闲线程
pool.execute(new rubthread());
pool.execute(new rubthread());
while (true) {
pool.execute(new Runnable() {
@Override
public void run() {
System.out.println("创建线程:" + Thread.currentThread().getName());
try {
// 休眠3000毫秒
thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
}
}
setPriority方法:
使用setPriority 方法对线程的优先级进行设置 范围为(1-10),默认为 5
public class Main {
public static void main(String[] args) {
// 创建子线程:打印数字1-26
Thread thread1 = new Thread("数字线程") {
@Override
public void run() {
for (int i = 1; i <= 26; i++) {
System.out.println(Thread.currentThread().getName() + "打印=>" + i + "[" + Thread.currentThread().getPriority() + "]");
}
}
};
// 创建子线程:打印字母A-Z
Thread thread2 = new Thread("字母线程") {
@Override
public void run() {
for (char i = 'A'; i <= 'Z'; i++) {
System.out.println(Thread.currentThread().getName() + "打印=>" + i + "[" + Thread.currentThread().getPriority() + "]");
}
}
};
thread1.setPriority(8); // 设置数字线程优先级=8
thread2.setPriority(1); // 设置字母线程优先级=1
// 启动子线程
thread1.start();
thread2.start();
}
}
Join方法:
join方法实现插队操作,
public class thread01 {
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread( new Runnable() {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("T1:"+i);
}
}
}) ;
Thread t2= new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("T2:"+i);
}
}
});
// 启动线程
t1.start();
t2.start();
// 插队到主线程前
t1.join();
t2.join();
}
}
interrupt( )方法:
中断线程,当一个线程要执行一个长时间任务的时候,就可能使用interruput来中断线程。
public class Demo {
public static void main(String[] args) {
System.out.println("主线程开始");
// 创建子线程
Thread thread = new Thread() {
public void run() {
System.out.println("子线程开始执行,进入RUNNABLE状态");
try {
// 子线程休眠6秒,进入TIMED_WAIT计时等待状态
Thread.sleep(1000 * 6);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("子线程结束执行,进入TERMINATED状态");
}
};
// 启动子线程
thread.start();
// main主线程休眠5秒
try {
Thread.sleep(1000 * 3);
} catch (InterruptedException e) {
e.printStackTrace();
}
// main主线程修改子线程的中断状态=true
// 子线程检测中断状态=true,则抛出InterruptedException,子线程执行结束
thread.interrupt();
System.out.println("主线程结束!");
}
}
yield( )方法
线程会调用Yieid方法来告诉JVM愿意让出CPU给其他线程,当时采不采用就取决于,当前JVM调度模型 :分时调度,抢占调度
public class Demo4 {
public static void main(String[] args) {
System.out.println("主线程启动!");
Thread t1 = new Thread() {
@Override
public void run() {
for (int i = 0; i < 50; i++) {
System.out.println(i);
}
}
};
Thread t2 = new Thread() {
@Override
public void run() {
for (char i = 'A'; i <'z'; i++) {
System.out.println("让个他");
// 调用yeild方法让出本次CPU资源
Thread.yield();
System.out.println(i);
}
}
};
t1.start();
t2.start();
}
}
同时日常使用中,除了有我们可以感知的用户线程外,还有线程的守护者,这就是守护线程
守护线程如同骑士一般,默默守护着用户线程
setDaemon:
设置守护线程
public class Demo5 {
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread() {
@Override
public void run() {
while(true) {
System.out.println("login-------");
}
}
};
// 设置守护线程
t1.setDaemon(true);
t1.start();
Thread t2 = new Thread() {
@Override
public void run() {
while (!isInterrupted()) {
System.out.println("User-----------");
}
System.out.println("User结束!-------------------------");
}
};
t2.start();
Thread.sleep(10);
t2.interrupt();
System.out.println("主线程结束!");
}
}