一、线程的相关概念
进程
线程
单线程和多线程的概念
并发和并行
二、线程的基本使用
1.创建线程的两种方式
2.线程应用案例1
public class ThreadUse01 {
public static void main(String[] args) {
//创建Cat对象可以当作线程使用
Cat cat = new Cat();
cat.start();//启动线程
//当main线程启动一个子线程Thread-0,主线程不会阻塞,会继续执行
for (int i = 0; i < 6; i++) {
System.out.println("主线程启动"+ i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
//当一个类继承了Thread类,该类就可以当作线程使用
class Cat extends Thread {
@Override
public void run() {//重写run方法,写上自己的业务逻辑
//循环来持续进行线程
int times = 0;//用来计算出现次数
while (true) {
System.out.println("喵喵,我是小猫咪" + ++times);
//让该线程休眠一秒,会抛出异常所以要try catch
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (times == 80) {//当次数到80后结束
break;
}
}
}
}
3.线程应用案例2
public class Thread02 {
public static void main(String[] args) {
Dog dog = new Dog();
// dog.start();//这里不能直接使用start方法
//创建一个Thread对象然后把dog对象放入Thread然后调用start,实际上底层使用了代理模式这个设计模式
Thread thread = new Thread(dog);
thread.start();
}
}
class Dog implements Runnable{
int count = 0;
@Override
public void run() {
while (true){
System.out.println("小狗汪汪叫hi"+ (++count));
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(count == 10){
break;
}
}
}
}
4.start()开始线程的底层原理
5.线程应用案例–多线程
public class Thread03 {
public static void main(String[] args) {
T1 t1 = new T1();
T2 t2 = new T2();
Thread thread1 = new Thread(t1);
Thread thread2 = new Thread(t2);
thread1.start();//启动第一个线程
thread2.start();//启动第二个线程
}
}
class T1 implements Runnable{
int count = 0;
@Override
public void run() {
while (true){//每隔一秒输出helloworld
System.out.println("hello,world"+(++count));
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(count == 10){
break;
}
}
}
}
class T2 implements Runnable{
int count = 0;
@Override
public void run() {
while (true){//每隔一秒输出helloworld
System.out.println("hi"+(++count));
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(count ==5){
break;
}
}
}
}
6.使用多线程模拟售票
问题到后面解决
public class Ticket01 {
public static void main(String[] args) {
//测试
SellTicket sellTicket01 = new SellTicket();
SellTicket sellTicket02 = new SellTicket();
SellTicket sellTicket03 = new SellTicket();
sellTicket01.start();
sellTicket02.start();
sellTicket03.start();//会导致多线程冲突线程不安全(不做处理)会导致超卖
}
}
//使用Thread方式
class SellTicket extends Thread {
private static int num = 100;//多个线程共享票数
@Override
public void run() {
while (true) {
if (num <= 0) {//如果票卖完了
System.out.println("售票结束");
break;
}
//休眠50毫秒
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("窗口" + Thread.currentThread().getName() + "售出一张票" + " 剩余票数" + (--num));
}
}
}
7.线程终止
public class ThreadExit {
public static void main(String[] args) throws InterruptedException {
T t = new T();
t.start();
//如果希望主线程来控制线程的退出 ,只需要改变loop
Thread.sleep(10*1000);//主线程休眠10秒然后让子线程退出
t.setLoop(false);
}
}
class T extends Thread{
private boolean loop = true;
@Override
public void run() {
while (loop){
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("T1");
}
}
public void setLoop(boolean loop) {
this.loop = loop;
}
}
8.线程常用方法1
public class Method01 {
public static void main(String[] args) throws InterruptedException {
T t = new T();
t.setName("jack");//设置名称
t.setPriority(Thread.MIN_PRIORITY);//设置优先级
t.start();
//主线程打印五个hi然后就中断子线程休眠
for (int i = 0; i < 5; i++) {
Thread.sleep(1000);
System.out.println("hi");
}
t.interrupt();//当执行到这里时就会中断t的休眠
}
}
class T extends Thread {
@Override
public void run() {
while (true) {
for (int i = 0; i < 100; i++) {
System.out.println("进行中");
}
try {
System.out.println("休眠中");
Thread.sleep(20000);
} catch (InterruptedException e) {
//当执行到interrupt方法时会捕获到一个中断异常
System.out.println("被中止了");
}
}
}
}
9.线程常用方法2(插队和礼让)
public class Method02 {
public static void main(String[] args) throws InterruptedException {
T1 t1 = new T1();
t1.start();
for (int i = 1; i <= 20; i++) {
System.out.println("hello" + i);
Thread.sleep(1000);
if (i == 5){
//join表示线程插队
// t1.join();
Thread.yield();//礼让,不一定成功
}
}
}
}
class T1 extends Thread {
private int count = 1;
@Override
public void run() {
while (true) {
System.out.println("hi" + (++count));
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (count == 20) {
break;
}
}
}
}
10.用户线程和守护线程
public class Method03 {
public static void main(String[] args) throws InterruptedException {
T2 t2 = new T2();
t2.setDaemon(true);//设置为守护线程
t2.start();
for (int i = 0; i < 10; i++) {
System.out.println("hello");
Thread.sleep(1000);
}
}
}
class T2 extends Thread{
@Override
public void run() {
while (true){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("hi");
}
}
}
11.线程的生命周期
12.线程的同步
public class Ticket01 {
public static void main(String[] args) {
//测试
SellTicket sellTicket3 = new SellTicket();
new Thread(sellTicket3).start();//会导致多线程冲突线程不安全(不做处理)会导致超卖
new Thread(sellTicket3).start();//会导致多线程冲突线程不安全(不做处理)会导致超卖
new Thread(sellTicket3).start();//会导致多线程冲突线程不安全(不做处理)会导致超卖
}
}
//使用synchronized实现线程同步
//使用Thread方式
class SellTicket implements Runnable {
private static int num = 100;//多个线程共享票
private boolean loop = true;
public synchronized void sell(){
if (num <= 0) {//如果票卖完了
System.out.println("售票结束");
loop = false;
return;
}
//休眠50毫秒
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("窗口" + Thread.currentThread().getName() + "售出一张票" + " 剩余票数" + (--num));
}
@Override
public void run() {//同步方法再同一时刻只能有一个线程来实现run方法
while (loop) {
sell();
}
}
}
13.互斥锁
class SellTicket extends Thread {
private static int num = 100;//多个线程共享票
private static boolean loop = true;
public static void sell() {
synchronized (SellTicket.class) {
if (num <= 0) {//如果票卖完了
System.out.println("售票结束");
loop = false;
return;
}
//休眠50毫秒
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("窗口" + Thread.currentThread().getName() + "售出一张票" + " 剩余票数" + (--num));
}
}
@Override
public void run() {//同步方法再同一时刻只能有一个线程来实现run方法
while (loop) {
sell();
}
}
}