java学习:线程1

一、自定义线程的创建方式

方式一 :
1. 自定义一个类继承Thread类。
2. 重写Thread类的run方法,把自定义线程的任务代码写在run方法上。
3. 创建Thread的子类对象,并且调用start方法启动一个线程。

注意:千万不要直接调用run方法,调用start方法的时候线程就会开启,线程一旦开启就会执行run方法中代码,如果直接调用
run方法,那么就 相当于调用了一个普通的方法而已。

方式二:
1. 自定义一个类实现Runnable接口。
2. 实现Runnable接口 的run方法,把自定义线程的任务定义在run方法上。
3. 创建Runnable实现类对象。
4. 创建Thread类 的对象,并且把Runnable实现类的对象作为实参传递。
5. 调用Thread对象 的start方法开启一个线程。

问题1: 请问Runnable实现类的对象是线程对象吗?
Runnable实现类的对象并 不是一个线程对象,只不过是实现了Runnable接口 的对象而已。
只有是Thread或者是Thread的子类才是线程 对象。

问题2: 为什么要把Runnable实现类的对象作为实参传递给Thread对象呢?作用是什么?
作用就是把Runnable实现类的对象的run方法作为了线程的任务代码去执行了。

推荐使用: 第二种 实现Runable接口的

原因: 因为java单继承 ,多实现的。

二、需求: 模拟3个窗口同时在售50张 票

问题1 :为什么50张票被卖出了150次?

出现 的原因: 因为num是非静态的,非静态的成员变量数据是在每个对象中都会维护一份数据的,三个线程对象就会有三份。

解决方案:把num票数共享出来给三个线程对象使用。使用static修饰。

问题2: 出现了线程安全问题

线程 安全问题的解决方案:sun提供了线程同步机制让我们解决这类问题的。

java线程同步机制的方式:

	方式一:同步代码块
		
		同步代码块的格式:
			
			synchronized(锁对象){
				需要被同步的代码...
			}

同步代码块要注意事项:
1. 任意的一个对象都可以做为锁对象。
2. 在同步代码块中调用了sleep方法并不是释放锁对象的。
3. 只有真正存在线程安全问题的时候才使用同步代码块,否则会降低效率的。
4. 多线程操作的锁 对象必须 是唯一共享 的。否则无效。

	方式二:同步函数  :  同步函数就是使用synchronized修饰一个函数。

同步函数要注意的事项 :
	1. 如果是一个非静态的同步函数的锁 对象是this对象,如果是静态的同步函数的锁 对象是当前函数所属的类的字节码文件(class对象)。
	2. 同步函数的锁对象是固定的,不能由你来指定 的。


推荐使用: 同步代码块。
	原因:
		1. 同步代码块的锁对象可以由我们随意指定,方便控制。同步函数的锁对象是固定 的,不能由我们来指定。
		2. 同步代码块可以很方便控制需要被同步代码的范围,同步函数必须是整个函数 的所有代码都被同步了。

出现线程安全问题的根本原因:
1. 存在两个或者两个以上 的线程对象,而且线程之间共享着一个资源。
2. 有多个语句操作了共享资源。
图片:
在这里插入图片描述

public class Demo4 extends Thread {
	public Demo4() {
	}

	public Demo4(String name) {
		super(name);
	}

	static int ticketNum = 50;
	static Object o= new Object();//多线程共享的锁对象必须是唯一的,不然不起作用

	@Override
	public void run() {
		
		while (true) {
//			synchronized(new Object()){//锁不住,因为每次的Object对象都是新的锁
//			synchronized("锁"){//锁得住
			synchronized(o){//任意对象都可以作为锁
				
				if (ticketNum > 0){
					System.out.println(currentThread().getName()+"卖出了" + ticketNum + "号票");
					ticketNum--;
					try {
						sleep(100);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}else{
					System.out.println(currentThread().getName()+"票已售完!");
					break;
				}
			}
		}

	}
	public static void main(String[] args) {
		Demo4 d1=new Demo4("窗口1");
		Demo4 d2=new Demo4("窗口2");
		Demo4 d3=new Demo4("窗口3");
		d1.start();
		d3.start();
		d2.start();
	}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值