------
Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
多线程
首先是对线程与进程的理解:
进程:正在进行中的程序。
线程:就是进程中一个执行单元或执行情景或执行路径
负责进程中程序执行的控制单元 。
一个进程中至少要有一个线程。
当一个进程中线程有多个时,就是多线程。
多线程解决的问题:可以让多部分代码同时执行。
线程:就是进程中一个执行单元或执行情景或执行路径
负责进程中程序执行的控制单元 。
一个进程中至少要有一个线程。
当一个进程中线程有多个时,就是多线程。
多线程解决的问题:可以让多部分代码同时执行。
-----------------------------------------------------------------------
线程创建的方法之一
步骤:
1,定义类继承Thread类。
2,覆盖Thread类中的run方法。
3,创建Thread类的子类对象创建线程对象。
4,调用线程对象的start方法开启线程。
线程要执行什么内容,线程自己肯定有定义,
这个定义就是run方法,这个方法中定义就是线程要运行的内容。
可是该run方法的内容并不是我们所需要的。
怎么能让线程去运行我们自定义的内容呢?
只有覆盖Thread类中的run方法。 覆盖之前需要先继承。
这就是为什么要继承Thread类并覆盖run方法的原因。
主线程要运行的任务都在main函数中。
自定义的线程要运行的任务都在run方法中。
run方法就是专门用于存储线程任务代码的地方。
步骤:
1,定义类继承Thread类。
2,覆盖Thread类中的run方法。
3,创建Thread类的子类对象创建线程对象。
4,调用线程对象的start方法开启线程。
线程要执行什么内容,线程自己肯定有定义,
这个定义就是run方法,这个方法中定义就是线程要运行的内容。
可是该run方法的内容并不是我们所需要的。
怎么能让线程去运行我们自定义的内容呢?
只有覆盖Thread类中的run方法。 覆盖之前需要先继承。
这就是为什么要继承Thread类并覆盖run方法的原因。
主线程要运行的任务都在main函数中。
自定义的线程要运行的任务都在run方法中。
run方法就是专门用于存储线程任务代码的地方。
class Demo extends Thread
{
private String name;
Demo(String name)
{
super();
this.name = name;
}
//将线程要运行的自定义的任务都封装到了run方法中。
public void run()
{
int[] arr = new int[3];
System.out.println(arr[3]);
for(int x=1; x<=10; x++)
{
System.out.println(name+"---"+x+":::::"+Thread.currentThread().getName());
}
}
}
class ThreadDemo2
{
public static void main(String[] args)
{
//创建了两个线程对象。
Demo d1 = new Demo("章三");
Demo d2 = new Demo("徐达");
d1.start();
d2.start();
System.out.println(4/0);
System.out.println("over");
}
}
创建线程方式二:
1,定义一个类实现Runnable接口。
2,覆盖Runnable接口中的run方法。
将线程要运行的代码存储到run方法中。
3,创建该接口的子类对象。
4,通过Thread类进行线程的创建,并将Runnable接口的子类对象作为Thread类的构造函数的实参进行传递。
为什么要传递呢?
让线程对象创建时,就要明确要运行哪个run方法,而这个run方法是需要被对象调用的,
所以将run方法所属的对象传递给Thread类的构造函数。
5,调用Thread类中的start方法开启线程。
class Ticket implements Runnable
{
private int num = 100;
public void run()
{
while(true)
{
if(num>0)
{
System.out.println(Thread.currentThread().getName()+".....sale....."+num--);
}
}
}
}
class TicketDemo2
{
public static void main(String[] args)
{
Ticket t = new Ticket();
//创建线程对象。
Thread t1 = new Thread(t);
Thread t2 = new Thread(t);
Thread t3 = new Thread(t);
Thread t4 = new Thread(t);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
--------------------------------------------------------------------
线程安全问题
安全问题产生的原因:1,多个线程在操作共享数据。
2,操作共享数据的代码有多条。
一个线程在执行多条操作共享数据的过程中,其他线程参数与了运算,这时就会发生安全问题。
想要分析是否安全问题:
依据:线程任务中有没有共享数据,该数据是否被多条语句操作啊。
解决方案:只要保证一个线程在执行多条操作共享数据的语句时,其他线程不能参与运算即可。
当该线程都执行完后,其他线程才可以执行这些语句。
代码表现:java中给我们提供具体的解决语句。
那就是同步代码块。
格式:
synchronized(对象)//对象可以是任意的对象。
{
需要被同步的语句。
}
同步的原理:其实就是将需要同步的代码进行封装,并在该代码上加了一个锁。
同步的好处:解决多线程的安全问题。
同步的弊端:会降低性能。
同步的前提:
必须要保证在同步中有多个线程。因为同步中只有一个线程该同步是没有意义。
必须要保证多个线程在同步中使用的是同一个锁。
必须保证多个线程使用的锁是同一个。
这时才成为多个线程被同步了。
-------------------------------------------------------------------------------
线程通信
有了新特性Lock,Condition。就可以解决这个问题了。
之前是有两个锁嵌套,容易死锁,
现在方案是只有锁,但是锁上可以加入多个监视器。
一个监视生产者,一个监视消费者。
有了新特性Lock,Condition。就可以解决这个问题了。
之前是有两个锁嵌套,容易死锁,
现在方案是只有锁,但是锁上可以加入多个监视器。
一个监视生产者,一个监视消费者。
import java.util.concurrent.locks.*;
class Resource
{
private String name;
private int count = 1;
private boolean flag;
//创建一个锁对象。
private final Lock lock = new ReentrantLock();
//创建一个生产者的监视器。
private Condition producer_con = lock.newCondition();
//创建一个消费者监视器。
private Condition consumer_con = lock.newCondition();
public void set(String name)//
{
//获取锁。
lock.lock();
try
{
while(flag)
try{producer_con.await();}catch(InterruptedException e){}
this.name = name + count;
count++;
System.out.println(Thread.currentThread().getName()+".....生产者......"+this.name);
flag = true;
consumer_con.signal();
}
finally
{
//释放锁。
lock.unlock();
}
}
public void get()//
{
lock.lock();
try
{
while(!flag)
try{consumer_con.await();}catch(InterruptedException e){}//t2 t3
System.out.println(Thread.currentThread().getName()+".........消费者......"+this.name);//Thread-2 消费 馒头1
flag = false;
producer_con.signal();
}
finally
{
lock.unlock();
}
}
}
//生产者
class Producer implements Runnable
{
private Resource r;
Producer(Resource r)
{
this.r = r;
}
public void run()
{
while(true)
{
r.set("袜子");
}
}
}
//消费者
class Consumer implements Runnable
{
private Resource r;
Consumer(Resource r)
{
this.r = r;
}
public void run()
{
while(true)
{
r.get();
}
}
}
class ProConDemo4
{
public static void main(String[] args)
{
Resource r = new Resource();
Producer pro = new Producer(r);
Consumer con = new Consumer(r);
//两个线程负责生产。
Thread t0 = new Thread(pro);
Thread t1 = new Thread(pro);
//两个线程负责消费。
Thread t2 = new Thread(con);
Thread t3 = new Thread(con);
t0.start();
t1.start();
t2.start();
t3.start();
}
}