当一个程序进入到内存运行,即变成了一个进程,进程是处于运行过程中的程序,并且具有一定的独立功能
比如正在运行中的(QQ、迅雷)
线程是进程中的一个执行单元,负责当前进程中的程序的执行。
单线程:多个任务只能依次执行。上一个任务结束后,下一个任务开始(qq音乐一首一首播放)
多线程:多个任务同时执行(迅雷同时下载多个文件)
分时调度:所有线程轮流使用 CPU 的使用权,平均分配每个线程占用 CPU 的时间。
抢占式调度:优先让优先级高的线程使用 CPU,如果线程的优先级相同,那么会随机选择一个(线程随机性)
实际上,CPU(中央处理器)使用抢占式调度模式在多个线程间进行着高速的切换。对于CPU的一个核而言,某个时刻,只能执行一个线程,而 CPU的在多个线程间切换速度相对我们的感觉要快,看上去就是在同一时刻运行。(CPU调度)
创建基本线程类有四种方式:
实现Runnable接口
继承Thread类
使用JDK 8 的Lambda
使用Callable和Future
方法 | 说明 |
---|---|
start() | 启动线程 |
setName(String name) | 设置线程名称 |
setPriority(int priority) | 设置线程优先级,默认5,取值1-10 |
join(long millisec) | 挂起线程xx毫秒,参数可以不传 |
interrupt() | 终止线程 |
isAlive() | 测试线程是否处于活动状态 |
Thread静态(static)方法
方法 | 说明 |
---|---|
yield() | 暂停当前正在执行的线程对象,并执行其他线程。 |
sleep(long millisec)/sleep(long millis, int nanos) | 挂起线程xx秒,参数不可省略 |
currentThread() | 返回对当前正在执行的线程对象的引用 |
holdsLock(Object x) | 当前线程是否拥有锁 |
public class MyThread implements Runnable{
@override
public void run(){
System.out.println("正在运行"+Thread.currentThread().getName());
}
public static void main(String[] args) {
MyThread t = new MyThread();
new Thread(t).start();
}
}
public class MyThread extends Thread{
@Override
public void run() {
System.out.println("正在运行"+Thread.currentThread().getName());
}
public static void main(String[] args) {
MyThread t = new MyThread();
t.start();
}
}
//callable的接口定义
public interface Callable<V> {
V call() throws Exception;
}
public class MyThread implements Callable<Boolean> {
@Override
public Boolean call() throws Exception {
System.out.println("call方法在执行");
return true;
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
MyThread callable = new MyThread();
//创建1个线程
ExecutorService ser = Executors.newFixedThreadPool(1) ;
//提交执行
Future<Boolean> result = ser.submit(callable) ;
//获取返回值,返回值Future也是一个接口,通过他的get()方法可以获得任务执行的返回值。
boolean b = result.get();
//因为get()方法的阻塞性,获取返回值以后主线程才会继续执行
ser.shutdown();//关闭
}
}
真正启动线程的是start()方法而不是run(),run()和普通的成员方法一样,可以重复使用,但不能启动一个新线程。
线程的状态可以使用getState()查看
public class TestPriority {
public static void main(String[] args) {
//默认优先级为5
System.out.println(Thread.currentThread().getName()+"---"+Thread.currentThread().getPriority());
Thread t0 = new Thread(new MyPriority()) ;
Thread t1 = new Thread(new MyPriority()) ;
Thread t2 = new Thread(new MyPriority()) ;
t0.setPriority(Thread.MIN_PRIORITY);//1
t0.start();
t1.setPriority(Thread.NORM_PRIORITY);//5
t1.start();
t2.setPriority(Thread.MAX_PRIORITY);//10
t2.start();
}
}
class MyPriority implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName() +"----"+ Thread.currentThread().getPriority());
}
}
setDaemon(boolean on)
isDaemon()
发生多个线程同时操作同一个资源的情况下,需要线程同步,线程同步其实是一种排队机制
同一进程的多个线程共享同一存储空间,带来方便,也带来了访问冲突,为保证访问的正确性,访问时接入锁机制synchronized 特点
不安全 案例1
//抢票案例
public class demo{
public static void main(String[] args) {
BuyTickNum buyTickNum = new BuyTickNum();//需要锁的对象是变化的量
new Thread(buyTickNum,"小明").start();
new Thread(buyTickNum,"黄牛").start();
new Thread(buyTickNum,"小红").start();
}
}
class BuyTickNum implements Runnable{
private int ticketNums = 10 ;
boolean flag = true ;
@Override
public void run() {
//买票
while(flag){
buy();
}
}
//需要加上synchronized关键字 同步方法
private void buy(){
//判断是否有票
if(ticketNums <= 0){
flag = false ;
return ;
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
//抢票
System.out.println(Thread.currentThread().getName() + ":抢到了"+ticketNums--);
}
}
不安全 案例2
public static void main(String[] args) {
List<String> list = new ArrayList<>();
for (int i = 0; i < 10000; i++) {
new Thread(()->{
list.add(Thread.currentThread().getName()) ;
}).start();
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(list.size());//输出结果不到10000
}
synchronized 关键字
同步块 synchronized(object){ }
同步方法执行的原理
第一个线程访问,锁定同步监视器,执行其中代码。
第二个线程访问,发现同步监视器被锁定,无法访问。
第一个线程访问完毕,解锁同步监视器
第二个线程访问,发现同步监视器没有锁,然后锁定并访问
//
public class demo{
public static void main(String[] args) {
BuyTickNum buyTickNum = new BuyTickNum();//需要锁的对象是变化的量
new Thread(buyTickNum,"小明").start();
new Thread(buyTickNum,"黄牛").start();
new Thread(buyTickNum,"小红").start();
}
}
class BuyTickNum implements Runnable{
private int ticketNums = 10 ;
boolean flag = true ;
@Override
public void run() {
//买票
while(flag){
buy();
}
}
//加上synchronized关键字 同步方法
private synchronized void buy(){
//判断是否有票
if(ticketNums <= 0){
flag = false ;
return ;
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
//抢票
System.out.println(Thread.currentThread().getName() + ":抢到了"+ticketNums--);
}
}
public static void main(String[] args) {
List<String> list = new ArrayList<>();
for (int i = 0; i < 10000; i++) {
new Thread(()->{
synchronized(list){//加了同步块
list.add(Thread.currentThread().getName()) ;
}
}).start();
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(list.size());//输出结果不到10000 ,因为线程还没结束就打印输出了
}
/**
* Java线程:并发协作-死锁
*/
public class Test {
public static void main(String[] args) {
DeadlockRisk dead = new DeadlockRisk();
MyThread t1 = new MyThread(dead, 1, 2);
MyThread t2 = new MyThread(dead, 3, 4);
MyThread t3 = new MyThread(dead, 5, 6);
MyThread t4 = new MyThread(dead, 7, 8);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
class MyThread extends Thread {
private DeadlockRisk dead;
private int a, b;
MyThread(DeadlockRisk dead, int a, int b) {
this.dead = dead;
this.a = a;
this.b = b;
}
@Override
public void run() {
dead.read();
dead.write(a, b);
}
}
class DeadlockRisk {
private static class Resource {
public int value;
}
private Resource resourceA = new Resource();
private Resource resourceB = new Resource();
public int read() {
synchronized (resourceA) {
System.out.println("read():" + Thread.currentThread().getName()
+ "获取了resourceA的锁!");
synchronized (resourceB) {
System.out.println("read():" + Thread.currentThread().getName()
+ "获取了resourceB的锁!");
return resourceB.value + resourceA.value;
}
}
}
public void write(int a, int b) {
synchronized (resourceB) {
System.out.println("write():" + Thread.currentThread().getName()
+ "获取了resourceA的锁!");
synchronized (resourceA) {
System.out.println("write():"
+ Thread.currentThread().getName() + "获取了resourceB的锁!");
resourceA.value = a;
resourceB.value = b;
}
}
}
}
可重入锁使用方法
private final ReentrantLock lock = new ReentrantLock() ;
try{
lock.lock();
//处理任务
}catch(Exception ex){
}finally{
lock.unlock(); //释放锁
}
public class demo{
public static void main(String[] args) {
BuyTickNum buyTickNum = new BuyTickNum();
new Thread(buyTickNum,"小明").start();
new Thread(buyTickNum,"黄牛").start();
new Thread(buyTickNum,"小红").start();
}
}
class BuyTickNum implements Runnable{
private int ticketNums = 10 ;
//锁
private final ReentrantLock lock = new ReentrantLock() ;
boolean flag = true ;
@Override
public void run() {
//买票
while(flag){
try{
lock.lock();//获取锁
buy();//不安全的方法
}finally {
lock.unlock();//释放锁
}
}
}
private void buy(){
//判断是否有票
if(ticketNums <= 0){
flag = false ;
return ;
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
//抢票
System.out.println(Thread.currentThread().getName() + ":抢到了"+ticketNums--);
}
}
作用与用法
synchronized(lock){
while(flag){
lock.wait();
}
doAction();
}
synchronized(lock){
flag = false;
lock.notifyAll();
}
等待线程在 `wait();` 阻塞时释放锁,唤醒线程在执行结束时释放锁
等待线程可能不止一条,被唤醒时不一定能获取锁
如果条件被其他获取锁的等待线程修改,那么后续获得锁的等待线程会继续等待
等待线程与唤醒线程必须使用同一个锁
`notify();` 只能随机唤醒一条线程
并发协作
//并发协作模型”生产者/消费者模式”->管程法(利用管道容器来处理)
public class TestPc {
public static void main(String[] args) {
SynContiner continer = new SynContiner() ;
new Thread(new Productor(continer) ).start();
new Thread(new Cunsumer(continer)).start();
}
}
//产品
class Chicken{
public int id ;
public Chicken(int id){
this.id = id ;
}
}
//生产者 只管生产
class Productor implements Runnable{
private SynContiner continer ;
public Productor(SynContiner continer ){
this.continer = continer ;
}
@Override
public void run() {
for (int i = 1; i <= 100; i++) {
continer.Push(new Chicken(i));
System.out.println("生产了"+i+"只鸡");
}
}
}
//消费者 只管消费
class Cunsumer implements Runnable{
private SynContiner continer ;
public Cunsumer(SynContiner continer){
this.continer = continer ;
}
@Override
public void run() {
for (int i = 1; i <= 100; i++) {
System.out.println("消费了"+continer.Pop().id+"只鸡");
}
}
}
//管道容器缓冲区
class SynContiner{
//容器容量
Chicken[] chickens = new Chicken[10] ;
//容器计数器
int count = 0;
//生产者 生产鸡
public synchronized void Push(Chicken chicken){
//如果容器满了,需要等待生产者消费
if(count == chickens.length-1){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//如果容器没满->丢产品进去
chickens[count] = chicken;
count++ ;
//可以通知消费者消费了
this.notifyAll();
}
//消费者 消费鸡(返回消费了的那只鸡)
public synchronized Chicken Pop(){
if(count == 0){
//没有鸡了,等生产者生产
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
count-- ;
Chicken chicken = chickens[count];
//吃完了通知
this.notifyAll();
return chicken;
}
}
/*
*协作模型:生产者消费者实现方式二:信号灯法
* 借助标志位
*/
public class CooperationTest {
public static void main(String[] args) {
Tv tv =new Tv();
new Player(tv).start();
new Watcher(tv).start();
}
}
//生产者 演员
class Player extends Thread{
Tv tv;
public Player(Tv tv) {
this.tv = tv;
}
public void run() {
for(int i=0;i<20;i++) {
if(i%2==0) {
this.tv.play("奇葩说");
}else {
this.tv.play("太污了,喝瓶立白洗洗嘴");
}
}
}
}
//消费者 观众
class Watcher extends Thread{
Tv tv;
public Watcher(Tv tv) {
this.tv = tv;
}
public void run() {
for(int i=0;i<20;i++) {
tv.watch();
}
}
}
//同一个资源 电视
class Tv{
String voice;
//信号灯
//T 表示演员表演 观众等待
//F 表示观众观看 演员等待
boolean flag = true;
//表演
public synchronized void play(String voice) {
//演员等待
if(!flag) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//表演
System.out.println("表演了:"+voice);
this.voice = voice;
//唤醒
this.notifyAll();
//切换标志
this.flag =!this.flag;
}
//观看
public synchronized void watch() {
//观众等待
if(flag) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//观看
System.out.println("听到了:"+voice);
//唤醒
this.notifyAll();
//切换标志
this.flag =!this.flag;
}
}
public class TestPool {
public static void main(String[] args) {
//1.创建服务,创建线程池
//ExecutorService:真正的线程池接口
//newFixedThreadPool 参数:线程池大小
ExecutorService service = Executors.newFixedThreadPool(10) ;
//执行:void excute(Runnable command)
service.execute(new MyThread());
service.execute(new MyThread());
service.execute(new MyThread());
service.execute(new MyThread());
//关闭线程
service.shutdown();
}
}
class MyThread implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"--启动");
}
}
原文:https://www.cnblogs.com/wchaojie/p/14324755.html