这里写自定义目录标题
什么是进程什么是线程
进程:1 进程表示的是资源统一分配,任务调度,一般是程序调用
线程:进程包含线程,进程里可以有多个线程
线程的启动
第一种线程 currentThread
找到正在执行的线程 currentThread
public static void main(String[] args){
System.out.println(Thread.currentThread().getName());
}
代码运行结果与代码的执行顺序无关
/**
* @Author: judy
* @Description: run 方法是main方法调用和start方法是线程调用的 ,run表示的同步进行, start表示异步进行
* @Date: Created in 8:59 2019/2/22
*/
public class CurrentThreadDemo extends Thread {
@Override
public void run() {
super.run();
System.out.println("this is run="+currentThread().getName());
}
public CurrentThreadDemo(){
System.out.println("this is 构造方法="+currentThread().getName());
}
public static void main(String[] args){
CurrentThreadDemo currentThreadDemo = new CurrentThreadDemo();
currentThreadDemo.start();
}
}
start 的 作用,start在代码中的位置与执行结果不一致
public class myThreadDemo extends Thread {
@Override
public void run() {
super.run();
System.out.println("this is first demo");
}
public static void main(String[] args){
myThreadDemo myThreadDemo =new myThreadDemo();
myThreadDemo.start();
System.out.println("maybe should end");
}
}
maybe should end
this is first demo
为什么会有runable
由于java是单继承,所以当我们适应extends继承Thread的时候发现自己已经继承了其他类,所以这个可以使用runable,实现效果是一样的,并且Thread构造方法可以参数可以是ruable
如何使用
/**
* @Author: judy
* @Description: run运行,展示Thread的构造函数可以使用runable, 以及为什么使用runnable ,
* @Date: Created in 23:39 2019/2/21
*/
public class myRunnableOneDemo implements Runnable {
@Override
public void run() {
System.out.println("运行中");
}
public static void main(String[] args){
Runnable runnable= new myRunnableOneDemo();
Thread thread = new Thread(runnable);
thread.start();
System.out.println("运行结束");
}
}
什么线程安全
线程安全指的是多个线程一起运行的时候变量的值最终是正确的,不会多也不会少.
下面代码是线程安全的,因为他们线程之间没有共享变量,所以数据是安全的
/**
* @Author: judy
* @Description: 不共享变量(数据的情况)
*
* @Date: Created in 7:55 2019/2/22
*/
public class VariableSecurityDemo extends Thread{
private int count =5;
public VariableSecurityDemo(String name){
super();
this.setName(name);
}
@Override
public void run() {
super.run();
while (count>0){
count--;
System.out.println("由"+this.currentThread().getName()+"计算count is value"+count);
}
}
public static void main(String[] args){
//每个线程自己有一个count,不共享,所以数据都是安全的
VariableSecurityDemo variableSecurityDemo1= new VariableSecurityDemo("A");
VariableSecurityDemo variableSecurityDemo2= new VariableSecurityDemo("B");
VariableSecurityDemo variableSecurityDemo3= new VariableSecurityDemo("C");
VariableSecurityDemo variableSecurityDemo4= new VariableSecurityDemo("D");
variableSecurityDemo1.start();
variableSecurityDemo2.start();
variableSecurityDemo3.start();
variableSecurityDemo4.start();
}
}
什么是线程不安全
线程不安全指的是大家对同一个变量进行修改操作,最终到导致结果不一致,不正确
/**
* @Author: judy
* @Description: 共享数据
* @Date: Created in 8:03 2019/2/22
*/
public class ShareDataDemo extends Thread {
private int count = 6;
/**
* 1 取得原有i值;
* 2 计算i-1;
* 3 对i 进行赋值;
* 多个线程对统一对象中的同一个实例变量进行操作
*/
@Override
public void run() {
super.run();
count--;
System.out.println(this.currentThread().getName()+"计算count is="+count);
}
public static void main(String[] args){
ShareDataDemo shareDataDemo = new ShareDataDemo();
Thread thread1= new Thread(shareDataDemo,"1");
Thread thread2= new Thread(shareDataDemo,"2");
Thread thread3= new Thread(shareDataDemo,"3");
Thread thread4= new Thread(shareDataDemo,"4");
Thread thread5= new Thread(shareDataDemo,"5");
Thread thread6= new Thread(shareDataDemo,"6");
thread1.start();
thread2.start();
thread3.start();
thread4.start();
thread5.start();
thread6.start();
}
}
如何变成线程安全
变线程安全有很很多种做法,目前介绍的是synchronized , 为什么加sync就会线程安全,其实就是实现同步效果,一个一个的运行, 这样就不会出现两个线程同时操作一个变量,导致最终结果不正确.
@Override
synchronized public void run() {
super.run();
count--;
System.out.println(this.currentThread().getName()+"计算count is="+count);
}
如何看线程当前的状态
使用 isAlive( )
/**
* @Author: judy
* @Description: isAlive 表示线程处于什么状态
* @Date: Created in 9:18 2019/2/22
*/
public class MyThread extends Thread {
@Override
public void run() {
//线程处于什么状态
System.out.println("run="+this.isAlive());
}
}
class run{
public static void main(String[] args) throws InterruptedException {
MyThread myThread = new MyThread();
System.out.println("begin=="+myThread.isAlive());
myThread.start();
Thread.sleep(1000);
System.out.println("end=="+myThread.isAlive());
}
}
查看当前线程是否中断
查看线程终端总共有两种方式
1 使用isInterrupted()
2使用interrupt()
public class MyThread extends Thread {
@Override
public void run() {
super.run();
for (int i = 0; i <50000 ; i++) {
System.out.println("i="+(i+1));
}
}
public static void main(String[] args) throws InterruptedException {
// MyThread myThread = new MyThread();
// //start异步
// myThread.start();
// Thread.sleep(5000);
// //interrupt表示中断
// Thread.currentThread().interrupt();
Thread thread = new Thread();
thread.start();
Thread.sleep(5000);
thread.interrupt();
System.out.println("查看当前线程是否中断-1-"+thread.isInterrupted());
System.out.println("查看当前线程是否中断-2-"+thread.isInterrupted());
System.out.println("end");
}
为什么会出现两次false
使用 Thread.currentThread().interrupt(); 进行中断
为什么第一次是false第二次是true
interrupt 具有清理作用,会把第一次的状态清理,所以第二次的时候就是false
线程贡献cpu交给其他线程执行 yield
两次运行的时间是不一致,所以最终效果不一样
/**
* @Author: judy
* @Description: yield biaoshi
* @Date: Created in 10:50 2019/2/22
*/
public class YieldDemo extends Thread {
@Override
public void run() {
long timeStart = System.currentTimeMillis();
int count =0;
for (int i = 0; i < 500000; i++) {
// 测试使用yield和不使用的时间差
// Thread.yield();
count=count+(i+1);
}
long timeEnd= System.currentTimeMillis();
System.out.println("总共用时="+ (timeEnd-timeStart));
super.run();
}
public static void main(String[] args){
YieldDemo yieldDemo = new YieldDemo();
yieldDemo.start();
}
}
守护线程代码
/**
* @Author: judy
* @Description: 守护线程
* @Date: Created in 11:06 2019/2/22
*/
public class DaemonDemo extends Thread {
private int count = 0;
@Override
public void run() {
super.run();
while (true){
count++;
System.out.println("count="+(count));
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Run{
public static void main(String[] args) throws InterruptedException {
DaemonDemo daemonDemo = new DaemonDemo();
daemonDemo.setDaemon(true);
daemonDemo.start();
Thread.sleep(1000);
System.out.println("end");
}
}