线程
1.概念与原理
1.1线程和进程的概念
现在的操作系统是多任务操作系统,而多线程是实现多任务的一种方式
进程:是指内存中运行的应用程序,有自己独立的内存空间,可以独立的运行,进程彼此之间互不干扰,一个进程可以包含多个线程
线程:是进程中的一个执行流程,一个进程包含多个线程,线程与线程之间共享该进程的资源
进程和线程都是实现多任务的技术,但是进程是资源分配的基本单位,线程是程序执行的基本单位
1.2 java中的线程
在Java中 使用java.lang.Thread类或者Java.lang.Runnable接口编写代码来定义、实例化和启动一个新线程。
一个Thread类实例只是一个对象,和其它对象一样,具有变量和方法,生死于堆上。
2. 线程的创建与启动
2.1 继承Threat类
//使用一个类继承Threat类,然后重写run方法
//多线程抢占式运行
class MyThread extends Thread{
@Override
public void run() {
for (int i=0;i<100;i++)
System.out.println("线程1:"+i);
}
}
class MyThread1 extends Thread{
private String threadName;
@Override
public void run() {
for (int i=0;i<100;i++)
System.out.println("线程2:"+i);
}
}
public class A_Thread {
public static void main(String[] args) {
MyThread myThread = new MyThread();
myThread.start();
MyThread1 myThread1 = new MyThread1();
myThread1.start();
for (int i=0;i<100;i++)
System.out.println("主线程:"+i);
}
}
2.2 实现Runnable接口
class Methread implements Runnable{
@Override
public void run() {
for (int i=0;i<100;i++)
System.out.println("线程1:"+i);
}
}
class Methread1 implements Runnable{
@Override
public void run() {
for (int i=0;i<100;i++)
System.out.println("线程2:"+i);
}
}
public class B_Runnable {
public static void main(String[] args) {
Methread mt = new Methread();
Thread thread = new Thread(mt);
thread.start();
Thread thread1 = new Thread(new Methread1());
thread1.start();
for (int i=0;i<100;i++)
System.out.println("主线程:"+i);
}
}
2.3 线程的方法
构造方法:
Thread | 创建新的Thread对象 |
---|---|
Thread(Runnable target) | 传入一个实现Runnable接口的实例作为参数,创建Thread对象 |
Thread(Runnable target,String name) | 创建Thread对象并起名字 |
线程下面的方法
int | getPriority();返回线程优先级 |
---|---|
void | setPriority(int newPriority);更改线程优先级 |
class MyThread1 implements Runnable{
@Override
public void run() {
for (int i=0;i<=100;i++)
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
class Mythread2 implements Runnable{
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
public class A_Priority {
public static void main(String[] args) {
Thread thread1 = new Thread(new MyThread1(), "线程一");
Thread thread2 = new Thread(new Mythread2(), "二号");
thread1.setPriority(7);
//虽然thread1的优先级比较高,但执行的时候还是抢占式,并不会因为优先级高就先执行
//结果不可预期
thread1.start();
thread2.start();
}
}
/*二号:41
二号:42
线程一:87
二号:43
二号:44
二号:45
线程一:88
线程一:89*/
3.线程同步和锁
为什么要线程同步:当多个线程同时请求一个数据的时候,可能会导致数据不准确的情况
class SaleTicket implements Runnable{
@Override
public void run() {
int count=100;
while(true){
if (count<0)
break;
System.out.println(Thread.currentThread().getName()+"剩余票数:"+count);
count--;
}
}
}
public class A_NotTongBu {
public static void main(String[] args) {
SaleTicket saleTicket = new SaleTicket();
new Thread(saleTicket, "线程1").start();
new Thread(saleTicket, "线程2").start();
}
}
/*线程2剩余票数:36
线程2剩余票数:35
线程1剩余票数:98
线程1剩余票数:97
线程1剩余票数:96
线程1剩余票数:95
线程2剩余票数:34
线程2剩余票数:33
*/
对于这种情况我们可以在方法声明的时候加上一锁,可以使用synchronized关键字,也可以加在循环的时候,这样就可以防止多个线程在访问同一个资源的时候,避免出现线程不安全的情况。
4.死锁
死锁是线程的一种状态,当两个对象需要访问彼此所持有的资源,但是又不肯释放自身所持有的资源时,两个线程僵持住,就是死锁。
5.Object类下面与线程有关的方法
void wait() | 让当前线程等待,直到另一个线程调用当前对象的notify |
---|---|
void notify() | 唤醒线程池中等待的线程 |
void notifyAll() | 唤醒所有等待中的所有线程 |
6.线程的生命周期
线程的创建与启动 start
可以运行的状态 抢占 等待
执行状态 抢占 执行
阻塞 wait sleep 锁
消亡 destroy
7.生产者消费者模式
生产者,消费者,商品三者要遵循一定的规律,
当有商品时消费者可以消费,
当没有商品时消费者不能消费,生产者需要生产,
当商品栏满的时候生产者停止生产,消费者可以消费
class Goods{
private String name;
private String id;
private boolean isProduct;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public boolean isProduct() {
return isProduct;
}
public void setProduct(boolean product) {
isProduct = product;
}
public Goods(String name, String id, boolean isProduct) {
this.name = name;
this.id = id;
this.isProduct = isProduct;
}
}
class Customer implements Runnable{
private Goods goods;
public Customer(Goods goods) {
this.goods = goods;
}
@Override
public void run() {
while(true){
synchronized (goods){
if (!goods.isProduct()){
//不需要生产
System.out.println("消费者购买了:"+goods.getName()+",价格为:"+goods.getId());
goods.setProduct(true);
goods.notify();
}else{
try {
goods.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
class Productor implements Runnable{
private Goods goods;
public Productor(Goods goods) {
this.goods = goods;
}
@Override
public void run() {
int count=0;
int num=0;
while (num<100){
num++;
synchronized (goods){
if (goods.isProduct()){
if (count%2==0){
goods.setName("比亚迪元");
goods.setId("10");
goods.setProduct(false);
count++;
System.out.println("制造了第"+num+"辆:"+goods.getName()+",价格为:"+goods.getId());
}else{
goods.setName("比亚迪唐");
goods.setId("30");
goods.setProduct(false);
count++;
System.out.println("制造了第"+num+"辆:"+goods.getName()+",价格为:"+goods.getId());
}
goods.notify();
}else{
try {
goods.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
public class Test1 {
public static void main(String[] args) {
Goods goods = new Goods("MINI", "4.4", true);
Customer customer = new Customer(goods);
Productor productor = new Productor(goods);
new Thread(customer).start();
new Thread(productor).start();
}
}