首先看一下java中的多线程
1.多线程是合理充分利用了CPU,内存资源 。
2.多个线程同步操作一个加锁对象,效率是得不到提升的,记得在一个博客上看的一篇日志,将一个加锁的对象比喻成一个卫生间,同一个时间卫生间只容纳一个人,也就是一个进程对此持有对象。那么别的人只有在外面等着,此时的多进程显得是无力的。
Java中实现多线程有两种方式,一种是继承类Thread,另外一个是实现接口Runnable.无论是通过Thread类还是Runnable接口建立线程,都必须建立Thread类或它的子类的实例
首先看一个最简单的事例来简单的说一下java中线程的使用
1.继承Thread类
public class ThreadDemo extends Thread {
//使用继承Thread类的方法来创建线程类时,多个线程之间无法共享线程类的实例变量
private int i=10;
public void run(){
while(i>0){
System.out.println(this.getName()+"值为:"+i--);
}
}
public static void main(String[] args) {
new ThreadDemo().start();
new ThreadDemo().start();
}
}
输出结果如下:
Thread-0值为:10
Thread-0值为:9
Thread-0值为:8
Thread-0值为:7
Thread-0值为:6
Thread-0值为:5
Thread-0值为:4
Thread-0值为:3
Thread-0值为:2
Thread-0值为:1
Thread-1值为:10
Thread-1值为:9
Thread-1值为:8
Thread-1值为:7
Thread-1值为:6
Thread-1值为:5
Thread-1值为:4
Thread-1值为:3
Thread-1值为:2
Thread-1值为:1
2.实现Runnable接口
public class RunnableDemo implements Runnable {
private int i=10;
@Override
public void run() {
// TODO Auto-generated method stub
while(i>0){
System.out.println(Thread.currentThread().getName()+"值为:"+i--);
}
}
public static void main(String[] args) {
RunnableDemo runnableDemo=new RunnableDemo();
new Thread(runnableDemo, "A").start();
new Thread(runnableDemo, "B").start();
}
}
输出结果如下:
A值为:10
B值为:9
A值为:8
A值为:6
A值为:5
A值为:4
B值为:7
A值为:3
B值为:2
A值为:1
根据以上的两个事例可以看出继承类无法实现多线程对类中定义变量的引用。
下面写一个老生常谈的示例:刚接触java的时候写的是一个火车票售票的事例,下面先来写一个事例来引入同步(synchronized)的概念
车票的实体类:
public class Tickets {
private int totalTicket;
public Tickets(int totalTicket) {
super();
this.totalTicket = totalTicket;
}
public Tickets() {
super();
// TODO Auto-generated constructor stub
}
/**
* 获取 #{bare_field_comment}
* @return totalTicket
*/
public int getTotalTicket() {
return totalTicket;
}
/**
* 设置 #{bare_field_comment}
* @param totalTicket #{bare_field_comment}
*/
public void setTotalTicket(int totalTicket) {
this.totalTicket = totalTicket;
}
}
进程类
public class SaleInfo extends Thread {
private int getticketInfo;
private Tickets tickets;
private String name;
public void run(){
if (tickets.getTotalTicket()>=getticketInfo) {
System.out.println("可以取票"+getticketInfo);
tickets.setTotalTicket(tickets.getTotalTicket()-getticketInfo);
System.out.println("此时剩余的票是:"+tickets.getTotalTicket());
}else {
System.out.println("余票不足");
}
}
public SaleInfo(String name,Tickets tickets,int getticketInfo){
this.name=name;
this.tickets=tickets;
this.getticketInfo=getticketInfo;
}
}
测试类
public class MainDemo {
public static void main(String[] args) {
// TODO Auto-generated method stub
Tickets tickets=new Tickets(100);
new SaleInfo("A", tickets, 60).start();
new SaleInfo("B", tickets, 60).start();
}
}
结果如下:
可以取票60
可以取票60
此时剩余的票是:40
此时剩余的票是:-20
可以看到明显是错误的。
那么如何解决这个同步的问题呢?
这里引入了synchronized的概念,代码修改如下:
public void run(){
synchronized (tickets) {
if (tickets.getTotalTicket()>=getticketInfo) {
System.out.println("可以取票"+getticketInfo);
tickets.setTotalTicket(tickets.getTotalTicket()-getticketInfo);
System.out.println("此时剩余的票是:"+tickets.getTotalTicket());
}else {
System.out.println("余票不足");
}
}
}
运行结果如下:
可以取票60
此时剩余的票是:40
余票不足
看到这里想到了java中锁的机制。
下面写一个锁的示例
public class SalesInfo2 extends Thread {
private int getticketInfo;
private Tickets tickets;
private String name;
private final ReentrantLock reentrantLock=new ReentrantLock();
public SalesInfo2(String name,Tickets tickets,int getticketInfo){
this.name=name;
this.tickets=tickets;
this.getticketInfo=getticketInfo;
}
public void run(){
try {
reentrantLock.lock();
if (tickets.getTotalTicket()>=getticketInfo) {
System.out.println("可以取票"+getticketInfo);
tickets.setTotalTicket(tickets.getTotalTicket()-getticketInfo);
System.out.println("此时剩余的票是:"+tickets.getTotalTicket());
}else {
System.out.println("余票不足");
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}finally{
reentrantLock.unlock();
}
}
}
运行结果如下:
可以取票60
余票不足
此时剩余的票是:40
这里表示的是给程序上把锁,同一 时间只能有一个售票员持有对象,当该售票员释放锁之后才可以由别的售票员来操作,这种情况下是可以保证一致性,但是也会有很多弊端。