java基础—多线程

1、Thread类

package com.wjl.base;

public class MyThread extends Thread {
	/**
	 * 利用继承的特点
	 *    将线程名称传递 
	 * @param name
	 */
	public MyThread(String name) {
		super(name);
	} 
	public void run() {
		for(int i=0;i<20;i++) {
			//getName来自父类Thread
			System.out.println(getName()+"--"+i+"---");
		}
	}
}

测试

package com.wjl.test;

import com.wjl.base.MyThread;

/**
 * 多线程
 * @author wjl
 *
 */
public class Demo01 {
	public static void main(String[] args) {
		
		/*
		 * 多线程执行时,在栈内存中,每个执行线程都有一片自己所属的栈内存空间。
		 * 进行方法的压栈和弹栈。
		 */
		MyThread mt=new MyThread("业务1");
		mt.start();//开启一个新的线程
		for(int i=0;i<20;i++) {
			System.out.println("主线程"+"---"+i+"----");
		}
		
	}
}

Thread构造方法:

  • public Thread() 分配一个新的线程对象。
  • public Thread(String name) 分配一个指定名字的新的线程对象。
  • public Thread(Runnable target) 分配一个带有指定目标新的线程对象。
  • public Thread(Runnable target,String name) 分配一个带有指定目标新的线程对象并指定名字

常用方法:

  • public String getName() :获取当前线程名称。
  • public void start() :导致此线程开始执行; Java虚拟机调用此线程的run方法。
  • public void run() :此线程要执行的任务在此处定义代码。
  • public static void sleep(long millis) :使当前正在执行的线程以指定的毫秒数暂停(暂时停止执行)。
  • public static Thread currentThread() :返回对当前正在执行的线程对象的引用。

2、Runnable

public class MyRunnabe implements Runnable {
	@Override
	public void run() {
		for (int i = 0; i < 20; i++) {
			System.out.println(Thread.currentThread().getName()+"---"+i+"---");
		}
	}
}
import com.wjl.base.MyRunnabe;

public class Demo02 {
	public static void main(String[] args) {
		MyRunnabe mr=new MyRunnabe();
		//创建线程对象
		Thread thread=new Thread(mr, "业务2");
		thread.start();
		for (int i = 0; i < 20; i++) {
			System.out.println("主线程"+"---"+i+"----");
		}
	}
}

3、Thread和Runnable的区别

如果一个类继承Thread,则不适合资源共享。但是如果实现了Runable接口的话,则很容易的实现资源共享。
总结:
实现Runnable接口比继承Thread类所具有的优势:

  • 适合多个相同的程序代码的线程去共享同一个资源。
  • 可以避免java中的单继承的局限性。
  • 增加程序的健壮性,实现解耦操作,代码可以被多个线程共享,代码和线程独立。
  • 线程池只能放入实现Runable或Callable类线程,不能直接放入继承Thread的类

4、线程同步

4.1 同步代码块

同步代码块: synchronized 关键字可以用于方法中的某个区块中,表示只对这个区块的资源实行互斥访问。
格式:

synchronized(同步锁){
     需要同步操作的代码
}

同步锁:
对象的同步锁只是一个概念,可以想象为在对象上标记了一个锁.
1. 锁对象 可以是任意类型。
2. 多个线程对象 要使用同一把锁

/**
 * 同步代码块
 * @author wjl
 *
 */
public class Ticket implements Runnable {
	private int ticket=100;
	Object lock=new Object();
	
	//执行卖票操作
	@Override
	public void run() {
		while(true) {
			synchronized (lock) {
				if(ticket>0) {//有票
					try {
						Thread.sleep(100);//模拟出票时间
					} catch (Exception e) {
						e.printStackTrace();
					}
					
					//获取当前线程的名字
					String name=Thread.currentThread().getName();
					System.out.println(name+" 正在售"+ticket--+"---");
				}else {
					break;
				}
			}
		}
	}

}

测试

package com.wjl.test;

import com.wjl.ticket.Ticket;

public class Demo03Ticket1 {
	public static void main(String[] args) {
		Ticket ticket=new Ticket();
		Thread t1=new Thread(ticket,"窗口1");
		Thread t2=new Thread(ticket,"窗口2");
		Thread t3=new Thread(ticket,"窗口3");
		//同时卖票
		t1.start();
		t2.start();
		t3.start();
	}
}

4.2 同步方法

同步方法:使用synchronized修饰的方法,就叫做同步方法,保证A线程执行该方法的时候,其他线程只能在方法外等着

public synchronized void method(){
      可能会产生线程安全问题的代码
}
package com.wjl.ticket;

public class Ticket2 implements Runnable {
	private  int ticketNum=100;
	@Override
	public void run() {
		while(true) {
			sellTicekt();
		}
	}
	/**
	 * 锁对象 是 谁调用这个方法  就是谁
	 *    隐含 锁对象 就是 this
	 */
	public synchronized void sellTicekt() {
		if(ticketNum>0) {//有票
			try {
				Thread.sleep(50);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			
			//获取当前线程对象的名字
			String name=Thread.currentThread().getName();
			System.out.println(name+" 正在售"+ticketNum--+"---");
		}
	}

}

4.3 Lock锁

java.util.concurrent.locks.Lock 机制提供了比synchronized代码块synchronized方法更广泛的锁定操作,同步代码块/同步方法具有的功能Lock都有,除此之外更强大,更体现面向对象。
Lock锁也称同步锁,加锁与释放锁方法化了,如下:

  • public void lock() :加同步锁。
  • public void unlock() :释放同步锁。
    使用如下
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Ticket3 implements Runnable{
	private int ticketNum=100;
	Lock lock=new ReentrantLock();
	
	@Override
	public void run() {
		while(true) {
			lock.lock();
			if(ticketNum>0) {//有票
				try {
					Thread.sleep(50);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				//获取当前线程对象的名字
				String name = Thread.currentThread().getName();
				System.out.println(name+"正在售"+ticketNum--+"---");
			}
			lock.unlock();
		}
	}

}

5、线程状态

在API中 java.lang.Thread.State 这个枚举中给出了六种线程状态:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值