线程的概念

程序:是为完成特定任务,用某种语言编写的一组指令的集合,即指一段静态的代码,静态对象。
进程:是程序的一次执行过程,或是正在运行的一个程序,是一个动态的过程,有它自身的产生,存在和消亡的过程。-------生命周期
线程:进程可进一步细化为线程,是一个程序内部的一条执行路径
并行:多个CPU同时执行多个任务
并发:一个CPU(采用时间片)同时执行多个任务,比如秒杀平台,多个人做同件事

Thread创建

  1. 继承Thread类线程序
  2. 实现Runnable接口创建线程
  3. 使用Callable和Future创建线程
  4. 使用线程池例如Executor框架
    1.继承Thread类
    创建线程
class LTThread extends Thread{
    @Override
    public void run(){
    //必须重写run方法
        for (int i = 0; i < 101; i++) {
            System.out.println("我是新线程");
        }
    }

}
 

用start方法创建线程,调用run不会开启线程
start后线程不是马上开始,而是等待CPU有空闲时间时开始

public class Main {
    public static void main(String[] args) {
        LTThread ltThread=new LTThread();
        ltThread.start();
    }
}
 

介绍几个方法
1.setName()方法,为线程创建名字,必须在start前,否则无效。如果不set就有系统分配
2.getName()方法,返回线程名字。
3.setPriority()方法,设置优先级,这里set的是Java虚拟机中的优先级,调用时候不一定完全按照这个。只能作为调度的参考。
4.可以重写构造方法setName

2.Runnable接口创建线程

import java.util.*;

class T2 implements Runnable{
    public int a=100;
    @Override
    public void run(){
        for (int i = 0; i < 10; i++){
            System.out.println(Thread.currentThread().getName()+":"+a--);
        }
    }

}

public class Main {
    public static void main(String[] args) {
        T2 t2=new T2();
        Thread thread=new Thread(t2,"new");
        thread.start();
        Thread thread1=new Thread(t2,"new1");
        thread1.start();
    }
}
 

3.Callable

import java.awt.*;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;

class T3 implements Callable<Integer>{
    @Override
    public Integer call() throws Exception{
        System.out.println(Thread.currentThread().getName());
        int sum=0;
        for (int i = 0; i < 11; i++) {
            sum+=i;
        }
        return 0;
    }
}

public class Main {
    public static void main(String[] args) {
        T3 t3=new T3();
        FutureTask<Integer> futureTas=new FutureTask<Integer>(t3);
        //只有一格线程执行
        Thread thread=new Thread(futureTas,"test1");
        thread.start();
        Thread thread1=new Thread(futureTas,"test2");
        thread1.start();
       // System.out.println(futureTas.get());
    }
}

3.特殊创建方法

1.匿名内部类实现
2.lambda表达式实现

import java.util.*;

public class Main {
    public static void main(String[] args) {

        //匿名内部类实现
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("我是新的线程");
            }
        }).start();
        //lambda表达式创建
        new Thread(()->{
            System.out.println("I am newThread");
        }).start();
    }
}
 

3.继承Thread

import java.util.*;

public class Test extends Thread{
    public static void main(String[] args) {
        Test test =new Test();
        test.start();

    }
    @Override
    public void run() {
        System.out.println("new Thread");
    }
}
 

4.继承Runnable接口

import java.util.*;

public class Test implements Runnable{
    public static void main(String[] args) {
        Test test=new Test();
        Thread t1=new Thread(test);
        t1.start();
    }
    @Override
    public void run(){
        
    }
}
线程生命周期

在这里插入图片描述

Thread类中的常见方法

1.start()方法
启动线程,使得线程处于就绪态,还没有获得cpu使用权力。等待cpu
2.yield()
让线程回到就绪态。这样可以让其他线程更有机会获得cpu
3.currentThread(),返回当前线程
4.sleep()
在指定的毫秒数里面让当前正在执行的线程休眠等到休眠时间结束。从阻塞到就绪态。
5.join()
表示一定要该运行线程执行结束以后才能开始其他线程
6.wait()
7.notify()

线程同步-可见性

volite关键词

synchronized实例

同步

import java.util.*;

class T1 implements Runnable{
    //锁对象--当前实例对象
    //static对类要锁
    synchronized  public void f1() {
        System.out.println(Thread.currentThread().getName() + "开始了");
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();

        }
        System.out.println(Thread.currentThread().getName()+"结束了");
    }
    @Override
    public void run(){
                f1();
    }
}

public class Test {
    public static void main(String[] args) {
        T1 t=new T1();
        T1 tt=new T1();
        Thread t1=new Thread(t,"测试1");
        Thread t2=new Thread(t,"测试2");
        Thread t3=new Thread(tt,"测试3");
        t1.start();
        t2.start();
        t3.start();
    }
}
 

synchronized缺点

  • 效率低
  • 锁的释放情况少,只在程序正常执行和抛出异常时释放锁
  • 试图获得锁时不能设置超时
  • 不能中断一个正在试图获得锁的线程
  • 无法知道是否成功获得锁

lock接口和ReentrantLock类

Lock有比synchronized更精确的线程语义和更好的性能。synchronized会自动释放锁,而Lock一定要程序员手动释放锁,用try语句,最后在finally从句中释放锁

import java.util.*;
import java.util.concurrent.locks.ReentrantLock;

class T2 implements Runnable{
    //
    ReentrantLock reentrantLock=new ReentrantLock();
    public void f1() {
        reentrantLock.lock();
        try {

            System.out.println(Thread.currentThread().getName() + "开始了");
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "结束了");
        }
        finally {
            reentrantLock.unlock();
        }
    }
    @Override
    public void run(){
                f1();
    }
}

public class Test {
    public static void main(String[] args) {
        T2 t2=new T2();
        Thread thread=new Thread(t2,"测试1");
        thread.start();
        Thread thread1=new Thread(t2,"测试2");
        thread1.start();

    }
}
 

结束语

最后还有一些东西没学,就不写了,什么线程池之类的。就自己看看了,有时间补充吧。