Java之多线程

本文介绍了进程作为资源管理的基本单位和线程作为执行单元的概念,强调了一个程序至少一个进程,一个进程至少一个线程。接着详细讲解了如何在Java中创建多线程,包括继承Thread类和实现Runnable接口两种方式,并展示了线程的生命周期。最后,文章讨论了线程同步的重要性,列举了synchronized关键字的多种用法以及Lock锁的使用,以确保资源的正确访问和避免数据冲突。
摘要由CSDN通过智能技术生成

目录

进程与线程

多线程

 线程的生命周期

同步


进程与线程

 进程:是并发执行的程序在执行过程中分配和管理资源的基本单位,竞争计算机系统资源的基本单位.

线程:是进程的一个执行单元,是进程内科调度实体,比进程更小的独立运行的基本单位.线程也被称为轻量级进程.

一个程序至少一个进程,一个进程至少一个线程.

注:一个线程只属于一个进程,但是一个进程可以拥有多个线程,但至少一个线程.

多线程

 多线程是指一个进程同时存在多个执行体,按照几条不同的执行线索共同工作的情况.

创建线程:

方法一:继承Thread类

class MyThread extends Thread {
    
    //重写run方法
    @Override
    public void run (){
        //封装线执行的操作,例如:
        System.out.println(getName());
    }
}

class myThreadDemo {

	public static void main(String[] args) {
		
//		myThread mt1 = new myThread();
//		myThread mt2 = new myThread();
//      mt1.setName("1");
//      mt2.setName("2");
        //创建对象时设置线程名称
        myThread mt1 = new myThread("1");
        myThread mt2 = new myThread("2");

        //调用start方法,启动线程
		mt1.start();
		mt2.start();
}

方法说明:

start ( ) : 启动当前线程,调用当前线程的run ( ) 方法.

run ( ) : 需要重写Thread类中的此方法,将创建线程需要执行的操作声明在此方法中.

currentThread ( ) : 返回执行当前代码的线程对象的引用.

getName ( ) : 获取当前线程的名字.

setName (String name) : 设置当前线程的名字.

getPriority ( ) : 获取线程优先级.

setPriority ( ) : 设置线程优先级,优先级最高为10,默认为5,最低为1.优先级高的线程抢占到CPU执行权的概率高.

join ( ) : 在线程a中调用线程b的join ( ) ,此时线程a就会进入阻塞状态,直到线程b完全执行完之后,线程a再结束阻塞状态.

sleep (int millitime) : 让当前线程"睡眠"(停止执行)指定的毫秒数,在指定的毫秒时间内,当前线程是阻塞状态.

setDaemon (boolean on) : 设置线程为守护线程,当运行的线程均为守护线程时,Java虚拟机将退出.

方法2:实现Runnable接口

class MyRunnable implements Runnable {

    //重写run方法
	@Override
	public void run() {
            //封装线程执行的操作
		}
	}
	
}

class MyRunableDemo {

	public static void main(String[] args) {
		
		MyRunnable mr = new MyRunnable();
		
//		Thread t1 = new Thread(mr);
//		Thread t2 = new Thread(mr);
//		t1.setName("1");
//		t2.setName("2");
		
		Thread t1 = new Thread(mr,"1");
		Thread t2 = new Thread(mr,"2");
		
		t1.start();
		t2.start();
	}

}

实现Runnable接口相对于继承Thread类的好处:

1.避免了Java单继承的局限性.

2.适合多个相同程序的代码去处理同一个资源的情况,把线程和程序的代码,数据有效隔离,较好体现了面向对象的设计思想.

 线程的生命周期

df9c982a603f443aa898f2937b17455d.jpg

新建:线程已创建,尚未调用start()方法启动之前.

就绪:新建线程调用start()方法,或是阻塞线程的sleep()方法时间到或其他阻塞方式结束,进入就绪状态,此时线程有执行资格,但无执行权.

运行:此时线程得到CPU的执行权,既有执行资格,又有执行权,线程运行.

阻塞:线程被sleep()或其他阻塞式方法阻塞,此时线程既无执行资格,也无执行权,进入阻塞状态.

死亡:线程run()方法结束,线程死亡.

同步

 当多个线程同时操作一个可共享的资源变量时,将会导致数据不准确,相互之间产生冲突,因此加入同步锁以避免在该线程没有完成操作之前,不被其他线程调用,从而保证了该可共享资源变量的唯一性和准确性.

 1.使用synchronized关键字修饰代码块

格式:synchronized (Object o) { 需要被同步的代码块 },锁的对象是括号里的对象.

class SellTicket implements Runnable{
	
	private int tickets = 100;
	
	private Object obj = new Object();
	
	@Override
	public void run() {
		while(true) {
			synchronized (obj) {
				if(tickets>0) {
					try {
					    Thread.sleep(100);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					System.out.println(Thread.currentThread().getName()+"售出第"+(101-tickets)+"张票");
					tickets--;
				}
			}
			
		}
    }
}

2.使用synchronized关键字修饰非静态方法

格式:修饰符 synchronized 返回值类型 方法名 ( ) { },锁的对象是this.

class SellTicket implements Runnable{
	
	private int tickets = 100;
	
	@Override
	public void run() {
		while(true) {

			sell();
			
		}
	
	}

    private synchronized void sell () {非静态方法 锁的对象是this
        if(tickets>0) {
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName()+"售出第"+(101-tickets)+"张票");
			tickets--;
		}
    }
}

3.使用synchronized关键字修饰静态方法

格式:修饰符 static synchronized 返回值类型 方法名 ( ) { },锁的对象是本类类名.class

class SellTicket implements Runnable{
	
	private static int tickets = 100;
		
	@Override
	public void run() {
		while(true) {

			sell();
			
		}
	
	}

    private static synchronized void sell() {//静态方法 锁的对象是SellTicket.class
		if(tickets>0) {
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName()+"售出第"+(101-tickets)+"张票");
			tickets--;
		}
	}

}

4.Lock锁

void lock ( ) : 获得锁.

void unlock ( ) : 释放锁.

使用try...finally来保证锁的成功释放

class SellTicket implements Runnable {

	private int tickets = 100;

	private Lock lock = new ReentrantLock();

	@Override
	public void run() {
		while (true) {
			try {
				lock.lock();// 获得锁
				if (tickets > 0) {
					try {
						Thread.sleep(100);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					System.out.println(Thread.currentThread().getName() + "售出第" + (101 - tickets) + "张票");
					tickets--;
				}
			} finally {
				lock.unlock();// 释放锁
			}
		}
	}
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

浅释kkk

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值