应用程序:可以执行的软件
进程:多个线程的集合。进程中有多个不同的执行命令,进程是正在运行中的程序
在进程中,代码的执行顺序受主线程影响(main),因为主线程的线程优先级较高
线程:执行某一特定操作的路径,是执行逻辑的最小单位,每个线程之间互不影响,是自己在独立运行
多线程:为了提高程序的效率。 注:多线程下载并不提高宽带速度,而只是程序的效率,(断点续传会提高宽带速度)
多线程的应用场景:多线程下载,发邮件,多线程爬虫,分布式job(需要同时一个执行多个任务调度)
创建线程方式:
1 继承Thread类,重写run方法
2 实现runable接口方式
3 使用匿名内部类方式
4 使用callable
5 使用线程池创建
同步:代码从上至下执行
异步:多线程之间互不影响
通过继承和实现接口实现多线程:
package com.example.demo.thredDemo;
/**
* @author:qsc
* @date: 2019/4/25
* @time: 11:15
* @Describe: 创建多线程
*/
public class ThreadDemo01 {
/**
* 进程是正在运行的应用程序,进程是线程的集合
* 什么是线程:线程就是一条执行路径,一个独立的执行单元
* 什么是多线程,为了提高程序效率
* 怎么创建线程。有哪些方式:
* 1继承Thread类,重写run方法2 实现runable接口方式, 3 使用匿名内部类方式, 4 使用callable 5 使用线程池创建
*/
public static void main(String[] args) {
//1怎么调用线程
CreatThread creatThread = new CreatThread();
//2 启动线程,不是调用run方法,而是调用start方法
//3使用开启多线程后,代码不会从上往下执行,而是交替执行
//如果此时直接调用run方法,也就是creatThread.run()会从上至下执行(同步),也就是先执行creatThread中的方法,并没有开启异步多线程
creatThread.start();
//使用实现Runnable接口方式时,需要new Thread();
CreatThread02 creatThread02=new CreatThread02();
Thread thread=new Thread(creatThread02);
thread.start();
for (int j = 0; j < 10; j++) {
System.out.println("主线程:j=" + j);
}
}
}
/**
* 继承方式
*/
class CreatThread extends Thread {
/**
* run方法就是线程需要执行的任务或方法
*/
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("线程结果run:i=" + i);
}
}
}
/**
* 实现接口方式
*/
class CreatThread02 implements Runnable {
@Override
public void run() {
for (int m = 0; m < 10; m++) {
System.out.println("线程结果run:m=" + m);
}
}
}
使用接口方式比继承会更好一些:现在很多都是面向接口编程,单继承 多实现
使用匿名内部类创建多线程:
package com.example.demo.thredDemo;
/**
* @author:qsc
* @date: 2019/4/25
* @time: 13:09
* @Describe:
*/
public class ThreadDemo03 {
public static void main(String[] args) {
//
Thread thread= new Thread(new Runnable() {
@Override
public void run() {
//需要线程执行的代码
for (int i = 0; i < 10; i++) {
System.out.println("子线程结果run:i=" + i);
}
}
});
thread.start();
//主线程
for (int j = 0; j < 10; j++) {
System.out.println("主线程:j=" + j);
}
}
}
获取线程常用api方法:继承时
package com.example.demo.thredDemo;
/**
* @author:qsc
* @date: 2019/4/25
* @time: 13:20
* @Describe: 使用常用的线程api
*/
public class Thread04 {
public static void main(String[] args) {
//任何线程都肯定有一个主线程 Thread.currentThread()获取当前线程
//获取主线程的ID
System.out.println("主线程id:"+ Thread.currentThread().getId()+"主线程名:"+Thread.currentThread().getName());
CreatThread06 t = new CreatThread06();
t.start();
}
}
class CreatThread06 extends Thread {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//在这也可以用Thread.currentThread().getId()获取线程Id
System.out.println("线程名:"+getName()+" 线程Id:"+getId() + " 子线程结果run:i=" + i);
//当I=5时,停掉线程
if(i==5){
//这种方式不安全,不建议使用,有可能代码还没执行完,就终止
stop();
}
}
}
}
实现runable接口时
package com.example.demo.thredDemo;
/**
* @author:qsc
* @date: 2019/4/25
* @time: 13:20
* @Describe: 使用常用的线程api
*/
public class Thread04 {
public static void main(String[] args) {
//任何线程都肯定有一个主线程 Thread.currentThread()获取当前线程
//获取主线程的ID
System.out.println("主线程id:" + Thread.currentThread().getId() + "主线程名:" + Thread.currentThread().getName());
CreatThread06 t = new CreatThread06();
//在这里可以对线程起一个别名
Thread t1 = new Thread(t,"子线程");
t1.start();
}
}
class CreatThread06 implements Runnable {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//必须要用Thread.currentThread()获取当前线程
System.out.println("线程名:" + Thread.currentThread().getName() + " 线程Id:" + Thread.currentThread().getId() + " 子线程结果run:i=" + i);
//当I=5时,停掉线程
if (i == 5) {
//这种方式不安全,不建议使用,有可能代码还没执行完,就终止
Thread.currentThread().stop();
}
}
}
}
守护线程和非守护线程:
守护:和main线程相关的线程(比如gc线程),当主程序销毁,和主程序一起销毁
非守护线程:用户自己创建的线程,如果主程序停止掉,不会影响用户
package com.example.demo.thredDemo;
/**
* @author:qsc
* @date: 2019/4/25
* @time: 13:53
* @Describe: 用户线程是主线程创建的线程,是非守护线程
* 守护线程和主线程一起销毁
*/
public class test01 {
public static void main(String[] args) {
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("子线程:" + i);
}
}
});
t1.setDaemon(true); //为true时,表示为守护线程,可以把他注掉,对比结果
t1.start();
for (int i = 0; i < 30; i++) {
System.out.println("主线程:" + i);
}
System.out.println("主线程执行完毕");
}
}
多线程的几种运行状态: 新建状态,准备状态,运行状态,阻塞状态,停止状态
jion():一个线程A,另一个线程B,A线程调用B .join()方法时。作用就是:A线程等待B线程执行完之后,再继续执行操作。
在某种程度上可以说,把多线程又变成了单线程(正常情况下很少这样做)
package com.example.demo.thredDemo;
/**
* @author:qsc
* @date: 2019/4/25
* @time: 14:29
* @Describe:
*/
public class test02 {
public static void main(String[] args) {
Thread t1=new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 60; i++) {
System.out.println("子线程:" + i);
}
}
});
t1.start();
//需要让子线程先执行完毕后,怎么做
try {
t1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
for (int i = 0; i < 30; i++) {
System.out.println("主线程:" + i);
}
}
}
多线程分批处理数据:发送短信