线程
1.进程概述
进程简单来说就是计算机运行的一个程序
2.线程概述
线程是进程运行的最小单元,或者说是线程是进程的一条执行路径。一个进程至少包含一个线程,如果一个进程包含多个线程,则称为多线程应用程序。例如百度云,可同时下载多个内容。
主线程:jvm运行程序会创建一个main线程(主线程),该线程负责执行main方法。
子线程:线程并不是孤立的,而是相互联系。假设在A线程中创建了B线程, 习惯上称A线程为父线程, 称B线程为子线程。
串行:
并发:
并行:
3创建线程
3.1创建线程的两种方法
1)一个是定义Thread类的子类
package Threadnew;
/**
* Author:wenyu
* 2019/9/25
*/
public class Demo01 {
public static void main(String[] args) {
//创建线程
Thread t1 = new subThread();
//启动线程
t1.start();
}
}
class subThread extends Thread{
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("这是子线程执行的代码:"+i);
}
}
}
2)一个定义Runnable接口的实现类
package Threadnew;
/**
* Author:wenyu
* 2019/9/25
*/
public class Demo02 {
public static void main(String[] args) {
//3)定义Runnable接口的实现类对象
Prime p =new Prime();
//4)创建线程,调用Thread(Runable)构造方法
Thread thread = new Thread(p);
//5)开启新的线程
thread.start();
}
}
//1)定义Runnable接口的实现类
class Prime implements Runnable{
//2)重写接口的run()方法
@Override
public void run() {
for (int i=0;i<100;i++){
System.out.println("这是子线程执行的程序:"+i);
}
}
}
3)其他创建线程的方式
package Threadnew;
/**
* Author:wenyu
* 2019/9/25
*/
public class Demo03 {
public static void main(String[] args) {
//Thread类实现了Runnable接口,SubThread继承了Thread类,SubThread也是Runnable接口的实现类
subThread thread =new subThread();
Thread t3 = new Thread(thread);
t3.start();
//
Thread t4 = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("这是匿名内部类中的内容:"+i);
}
}
});
t4.start();
new subThread().start();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("另外一个子线程:"+i);
}
}
}).start();
}
}
4线程的常用方法
currentThread() 返回当前线程
getName() 返回线程名称
isAlive() 判断线程是否处于活动状态
sleep() 线程休眠
interrupt() 中断线程 只是打了一个中断标志,不是真正的终止线程
yield() 放弃当前线程的cpu执行权 有可能刚放弃就重新获得
getPriority() 线程优先级 1-10 默认优先级是5 一般不做修改
setDaeman 守护线程 守护线程不能独立运行. 典型的守护线程就是垃圾回收线程
currentThread() setName() getName()
package Threadnew;
/**
* Author:wenyu
* 2019/9/25
*/
public class Demo04 {
public static void main(String[] args) {
subThread04 t1 = new subThread04();
Thread thread = new Thread(t1);
thread.setName("t1");
thread.start();
}
}
class subThread04 implements Runnable{
public subThread04(){
System.out.println("构造方法中打印当前线程:"+Thread.currentThread().getName());
}
@Override
public void run() {
System.out.println("run方法中打印当前线程:"+Thread.currentThread().getName());
}
}
isAlive()
package Threadnew;
/**
* Author:wenyu
* 2019/9/25
*/
public class Demo05 {
public static void main(String[] args) {
subThread subThread = new subThread();
System.out.println("before:"+subThread.isAlive());
subThread.start();
System.out.println("after:"+subThread.isAlive());
}
//使用静态内部类定义一个Thread线程类的子类,只在当前Demo05类的main方法中使用
static class subThread extends Thread{
@Override
public void run() {
System.out.println("run ="+this.isAlive());
}
}
}
sleep()
package Threadnew;
/**
* Author:wenyu
* 2019/9/25
*/
public class Demo06 {
public static void main(String[] args) {
subThread t1 = new subThread();
System.out.println(Thread.currentThread().getName()+": before: "+System.currentTimeMillis());
t1.start();
System.out.println(Thread.currentThread().getName()+": after: "+System.currentTimeMillis());
}
static class subThread extends Thread{
@Override
public void run() {
try {
System.out.println(Thread.currentThread().getName()+": before:"+System.currentTimeMillis());
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName() + ": after:" + System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
interrupt()
Java中有三种方式可以终止线程的执行:
- 使用退出标志,使线程正常退出, 想办法让run()运行结束
- 使用stop()强行终止,不建议使用
- 使用interrupt()中断线程, 仅仅在是当前线程中打了一个中断标志,并不是真正的终止线程.
package Threadnew;
/**
* Author:wenyu
* 2019/9/25
*/
public class Demo07 {
public static void main(String[] args) {
SubThread t = new SubThread();
t.start();
//main线程打印100行
for (int i = 0; i < 100; i++) {
System.out.println("main: " + i);
}
//中断子线程
t.interrupt();
//仅仅是给线程 加一个中断标志, 并没有终止线程
System.out.println(t.isInterrupted()); //true
}
static class SubThread extends Thread{
@Override
public void run() {
super.run();
for (int i = 0; i < 1000; i++) {
System.out.println("sub thread --> " + i);
}
}
}
}
在子线程中通过判断中断标志来结束线程
package Threadnew;
/**
* 子线程通过中断标志来退出程序
* Author:wenyu
* 2019/9/25
*/
public class Demo08 {
public static void main(String[] args) {
subThread t1 = new subThread();
t1.start();
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName()+i);
}
t1.interrupt();//中断子线程
System.out.println(t1.isInterrupted());
}
static class subThread extends Thread{
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
if(this.isInterrupted()){
System.out.println("当前程序线程被终止");
// break;
return;
}
System.out.println("subThread->"+i);
}
System.out.println("这是for循环之后的代码");
}
}
}
通过修改标志来结束线程
package Threadnew;
/**
* Author:wenyu
* 2019/9/25
*/
public class Demo09 {
public static void main(String[] args) {
subThread s1 = new subThread();
Thread t1 = new Thread(s1);
t1.start();
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName()+i);
}
//把子线程结束
s1.running=false;
}
static class subThread implements Runnable{
public boolean running = true; //线程运行标志
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
//检查线程状态
if (!running){
break;
}
System.out.println("subThread->"+i);
}
System.out.println("这是子线程中for循环之后的代码");
}
}
}
getPriority()
package Threadnew;
/**
* Author:wenyu
* 2019/9/25
*/
public class Demo10 {
public static void main(String[] args) {
subThread t1 = new subThread();
t1.setName("t1");
//设置线程优先级
t1.setPriority(1);
t1.start();
subThread t2 = new subThread();
t2.setName("t2");
//设置线程优先级
t2.setPriority(10);
t2.start();
}
static class subThread extends Thread{
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
}
getDeamon()
package Threadnew;
/**
* Author:wenyu
* 2019/9/25
*/
public class Demo11 {
public static void main(String[] args) {
subThread1 t1 = new subThread1();
t1.setName("t1");
t1.setDaemon(true);//将t1设为守护线程
t1.start();
subThread2 t2 = new subThread2();
t2.setName("t2");
t2.start();
//当t2线程执行完毕, JVM只有t1线程时,JVM会退出
}
static class subThread1 extends Thread{
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
static class subThread2 extends Thread{
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
}
查看线程状态 getState()
ackage Threadnew;
/**
* Author:wenyu
* 2019/9/25
*/
public class Demo12 {
public static void main(String[] args) throws InterruptedException {
subThread t1 = new subThread();
t1.setName("t1");
System.out.println(t1.getState());//NEW
t1.start();
System.out.println(t1.getState());//RUNNABLE
Thread.sleep(200);
System.out.println(t1.getState());//TERMINATED
Thread.sleep(1000);
System.out.println(t1.getState());//TERMINATED
}
static class subThread extends Thread{
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(this.getName()+":"+i);
}
}
}
}
5线程同步
线程同步机制是一种用于协调线程之间数据访问的机制.
Java平台的线程同步机制包括锁, volatile关键字, 相关的方法.Object类中wait()/notify()
1)同步代码块
package Threadnew;
/**
* Author:wenyu
* 2019/9/25
*/
public class Demo13 {
static int num = 100; //定义静态变量,作为共享数据
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
new subThread().start();
}
}
static class subThread extends Thread{
static final Object obj = new Object();
@Override
public void run() {
while (true){
//同步代码块同步实例方法
synchronized (obj) {
while (num>0){
System.out.println(Thread.currentThread().getName()+"--"+num--);
}
}
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
break;
}
}
}
}
2)同步方法
直接使用synchronized修饰方法
如果修饰实例方法就是同步实例方法
如果修饰静态方法,就是同步静态方法
package Threadnew;
/**
* Author:wenyu
* 2019/9/26
*/
public class Demo14 {
public static void main(String[] args) {
Demo14 obj = new Demo14();
//开启两个线程
new Thread(new Runnable() {
@Override
public void run() {
Demo14.print();
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
Demo14.print2();
}
}).start();
}
public static void print(){
synchronized (Demo14.class) {//当前类的字节码作为锁对象
for (int i = 0; i < 50; i++) {
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
//同步静态方法, 使用当前类的运行时类对象,即类的字节码Test08.class作为锁对象
public synchronized static void print2(){
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
6.死锁
在多线程中,如果需要获取多个锁对象,如果获取锁对象的顺序不一样,可能造成相互等待的情况,被称为死锁。
7.volatile
volatile关键字的作用就是让变量在多个线程之间可见
package Threadnew;
/**
* Author:wenyu
* 2019/9/26
*/
public class Demo15 {
public static void main(String[] args) throws InterruptedException {
PrintString obj = new PrintString();
new Thread(new Runnable() {
@Override
public void run() {
try {
obj.printStringMethod();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
//Thread.sleep(100);
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName()+":"+i);
}
//修改main线程中的continuePrint
obj.setContinuePrint(false);
}
//定义打印字符串的类
static class PrintString{
//定义打印标志
private volatile Boolean continuePrint = true;
public PrintString setContinuePrint(Boolean continuePrint){
this.continuePrint=continuePrint;
return this;
}
public void printStringMethod() throws InterruptedException {
System.out.println("开始打印。。。");
while (continuePrint){
for (int i = 0; i < 10000; i++) {
if(continuePrint==true){
//Thread.sleep(10);
System.out.println(i);
}else {
break;
}
}
}
System.out.println("结束打印");
}
}
}