【多线程】的学习

本文介绍了Java中线程的基本概念,包括进程与线程的区别,以及创建线程的四种方式,重点讲解了通过继承Thread类和实现Runnable接口创建线程的方法。此外,还详细讨论了线程同步的重要性,展示了如何使用synchronized关键字实现同步代码块和同步方法,以确保线程安全。最后,文章通过死锁的例子说明了线程同步不当可能导致的问题,并给出了避免死锁的策略。
摘要由CSDN通过智能技术生成

多线程

线程与进程的概念

在程序执行过程中,一个应用程序就是一个进程,在这个进行运行过程中可能根据不同的功能创建多个线程

创建线程

创建获取线程的方式有四种,但是常用方式两种

1)继承Thread类重写run方法

2)实现runnable接口实现run方法

jdk1.5以后额外新增两种方法

3)实现callable接口实现call方法

4)线程池创建

继承Thread类重写run方法

public class MyThread extends Thread {
	// 创建类继承thread
	// 类似于自己为指定任务创建了一个线程类
	String name;

	public MyThread(String name) {
		super();
		this.name = name;
	}

	@Override
	public void run() {
		for (int i = 1; i <= 10; i++) {
			System.out.println(name + ":" + i);
		}
	}

	public static void main(String[] args) {
		// 使用线程类创建完成指定功能的线程对象并调用
		MyThread mt = new MyThread("线程1");// 创建线程对象
		mt.start();// 启动线程

		MyThread mt2 = new MyThread("线程2");// 创建线程对象
		mt2.start();// 启动线程
	}
}

实现runnable接口实现run方法

//创建实现类实现runnable接口 实现run方法
public class MyRunnable implements Runnable {
	// 实现runnable类似于创建的是线程要执行的任务类
	// 需要创建线程并将任务交给线程执行
	@Override
	public void run() {
		// 书写要执行的功能
		for (int i = 1; i <= 10; i++) {
			System.out.println( i);
		}
	}
	
	
	public static void main(String[] args) {
		//首先创建任务对象
		MyRunnable mr=new MyRunnable();//要执行的任务对象
		//创建线程并将任务交由线程执行
		Thread t=new Thread(mr);
		t.start();
		Thread t1=new Thread(mr);
		t1.start();
	}
}

区别

本质上thread也实现了runnable接口,不同的是java中继承为单继承,并且多个对象间不能实现资源的共享.实现runnable接口虽然可以实现资源的共享但是如果多个线程执行不相干不同的任务使用继承thread类的形式有时更简单

使用继承thread类重写run方法的形式实现多个线程售票

public class MyThread extends Thread {
	// 创建类继承thread
	// 类似于自己为指定任务创建了一个线程类
	static int ticket = 5;
	// 当前类可以使用static修饰变量的形式实现共享,但是如果多个线程类就不能实现资源的共享了

	@Override
	public void run() {
		while (true) {
			if (ticket > 0) {
				System.out.println("买票" + ticket--);
			} else {
				System.out.println("票已售空");
				break;
			}
		}
	}

	public static void main(String[] args) {
		// 使用线程类创建完成指定功能的线程对象并调用
		MyThread mt = new MyThread();// 创建线程对象
		mt.start();// 启动线程

		MyThread mt2 = new MyThread();// 创建线程对象
		mt2.start();// 启动线程
	}
}

使用实现runnable接口重写run方法的形式实现多线程售票

//创建实现类实现runnable接口 实现run方法
public class MyRunnable implements Runnable {
	// 实现runnable类似于创建的是线程要执行的任务类
	// 需要创建线程并将任务交给线程执行
	int ticket = 5;

	@Override
	public void run() {
		// 书写要执行的功能
		while (true) {
			if (ticket > 0) {
				System.out.println("买票" + ticket--);
			} else {
				System.out.println("票已售空");
				break;
			}
		}
	}

	public static void main(String[] args) {
		// 首先创建任务对象
		MyRunnable mr = new MyRunnable();// 要执行的任务对象
		// 创建线程并将任务交由线程执行
		//多个不同的线程对象使用的同一个任务对象,所以任务对象中所有属性共享
		Thread t = new Thread(mr);
		t.start();
		Thread t1 = new Thread(mr);
		t1.start();
	}
}

常用方法

构造方法

Thread(Runnable target)
使用指定任务对象创建线程
Thread(Runnable target, String name)
使用指定任务对象指定名称创建线程

常用方法

String getName()
返回该线程的名称。 如果在创建线程时指定线程名则获取,否则根据创建顺序命名为Thread-0 向后递增

int getPriority()
返回线程的优先级。

void setPriority(int newPriority)
更改线程的优先级。

void setName(String name)
改变线程名称,使之与参数 name 相同。

void start()
使该线程开始执行;Java 虚拟机调用该线程的 run 方法。

static void sleep(long millis)
在指定的毫秒数内让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度程序精度和准确性的影响。

static Thread currentThread()
返回对当前正在执行的线程对象的引用

线程同步(线程安全)

在线程执行时,有可能在进行判断时多个线程使用相同变量进行判断,导致数据的不准确,从而导致最终结果与预期结果不符

多线程同步

多个线程同时运行使用同一资源是对于每个线程同步执行(需要在前一个线程使用完毕后下一个线程才能继续使用)

在多线程同步时定义锁的概念,锁可以是一个对象或一个 方法,在线程执行时获取锁,执行介绍时释放,只有获取锁的线程可以执行否则进入等待

synchronized关键字

线程同步方法

在这里插入图片描述

同步代码块

使用同步关键字synchronized进行代码块的修饰,加入相应的对象作为锁

将需要同步执行的代码书写在同步代码块中

		synchronized (锁对象) {
   				 需要同步执行的代码块
		}
public class SynchronizedTest {
	public static void main(String[] args) {
		// MyR r = new MyR();
		// MyR r1 = new MyR();
		// Thread t1 = new Thread(r);
		// Thread t2 = new Thread(r1);
		// t1.start();
		// t2.start();

		MyT mt1 = new MyT();
		MyT mt2 = new MyT();
		mt1.start();
		mt2.start();
	}

}

class MyR implements Runnable {
	int t = 5;
	@Override
	public void run() {
		while (true) {
			synchronized (this) {//使用多个线程执行的任务对象当做锁对象
				if (t > 0) {
					System.out.println(Thread.currentThread().getName() + "正在做第" + t-- + "道题");
				} else {
					break;
				}
			}
		}
	}
}
class MyT extends Thread {
	static Integer t = 5;//将数据包装类当做锁对象
	@Override
	public void run() {
		while (true) {
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			synchronized (t) {
				if (t > 0) {
					System.out.println(Thread.currentThread().getName() + "正在做第" + t-- + "道题");
				} else {
					break;
				}
			}
		}
	}
}
同步方法

使用同步关键字synchronized进行方法的修饰,该方法的对象作为锁

//使用同步方法进行线程的同步
public class ThreadTest1 {
	public static void main(String[] args) {
		// MyRun mr1 = new MyRun();
		// Thread t1 = new Thread(mr1);
		// Thread t2 = new Thread(mr1);
		// t1.start();
		// t2.start();

		MyThr mt1 = new MyThr();
		MyThr mt2 = new MyThr();
		mt1.start();
		mt2.start();

	}
}

class MyRun implements Runnable {
	int t = 5;

	@Override
	public void run() {
		while (true) {
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			// 执行操作
			getT();
		}
	}

	// 使用同步关键字修饰方法
	public synchronized void getT() {
		// 在线程调用该方法是,获取该方法对象作为锁
		if (t > 0) {
			System.out.println(Thread.currentThread().getName() + "正在做第" + t-- + "道题");
		}
	}
}

class MyThr extends Thread {
	static int t = 5;

	@Override
	public void run() {
		while (true) {
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			// 执行操作
			getT();
		}
	}

	public static synchronized void getT() {
		// 在线程调用该方法是,获取该方法对象作为锁
		if (t > 0) {
			System.out.println(Thread.currentThread().getName() + "正在做第" + t-- + "道题");
		}
	}
}

死锁

当多个线程间使用多个锁资源,互相占用等待对方释放的过程

public class M {
	public static void main(String[] args) {
		Father f = new Father();
		Son s = new Son();
		FatherThread ft = new FatherThread(f, s);
		SonThread st = new SonThread(f, s);
		ft.start();
		st.start();
	}
}
//父类线程
class FatherThread extends Thread {
	Father f;
	Son s;
	public FatherThread(Father f, Son s) {
		super();
		this.f = f;
		this.s = s;
	}
	@Override
	public void run() {
		synchronized (f) {
			f.get();	 
			synchronized (s) {
				f.set();
			}
		}

	}
}
class SonThread extends Thread {
	Father f;
	Son s;
	public SonThread(Father f, Son s) {
		super();
		this.f = f;
		this.s = s;
	}
	@Override
	public void run() {
		synchronized (s) {
			s.get();
			synchronized (f) {
				s.set();
			}
		}

	}
}
class Father {
	public void get(){
		System.out.println("你给我成绩单,我给你玩具");
	}
	public void set(){
		System.out.println("给你玩具");
	}
}
class Son {
	public void get() {
		System.out.println("你给我玩具,我给你成绩单");
	}
	public void set() {
		System.out.println("给你成绩单");
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值