Java中的多线程的已经学习了两三天,现在就将我学习的心得与体会以及我对多线程的理解与大家分享一下,本博文绝对原创,如有理解不对或与读者理解有相悖之处,请留言,我们一起讨论一下,共同进步。
传统的实现多线程的方法有两种:
1. 通过继承Thread,并重写run方法来实现
2. 通过实现runnable接口重写run方法来实现
下面举例说明两种实现方法:
Public class MyThread extends Thread
{
Publicvoid run()
{
//要实现的代码
}
}
Public class MyThread2 implements Runnable
{
Publicvoid run()
{
//实现代码
}
}
Public class ThreadTest
{
Publicstatic void main(String[] args)
{
NewMyThread().start();
MyThread2 thread=new MyThread2();
NewThread(thread).start();
NewThread(thread).start();
}
}
通过上述代码,我们可以看出线程最基本的使用方法,同时我们也发现通过实现runnbale接口实现的线程。可以共享同一份数据,所以在编写多线程的程序是我们大多数还是会使用第二种方法的,第二种方法可以为我们带来很多意想不到的方便。
多线程的调用原理:
多线程的调用是CPU随机调用的,也就是说谁先得到cpu的资源谁先执行,如果一个线程开始执行,但是并不是得等到这个线程执行完以后别的线程才能调用,在上一个线程执行的过程期间,别的线程也会得到执行,只不过是多个线程一起争夺cpu,谁抢到谁执行,所以我们可以看到多个线程似乎是一起执行的。
多线程的安全问题:
安全问题要使用synchronized关键字,使用方法有synchronized块和synchronized方法,
Synchronized有一个锁(一个对象),当进入块或方法或锁变为0,其余用同一对象作为锁的方法不能被访问直到这个方法执行完。
下面给一个买票系统的例子:
package com.li;
public class ThreadSafe
{
/**
* @param args
*/
static TrainTicket ticket=new TrainTicket();
public static void main(String[] args)
{
new Thread(new Runnable()
{
@Override
public void run()
{
while(true)
{
ticket.ticketSale();
}
}
}).start();
new Thread(new Runnable()
{
@Override
public void run()
{
while(true)
{
ticket.ticketSale();
}
}
}).start();
}
static class TrainTicket
{
int ticketNumber=100;
public synchronized void ticketSale()
{
if(ticketNumber>0)
{
ticketNumber--;
System.out.println(Thread.currentThread().getName()+"sell"+ticketNumber);
}
}
}
}
执行结果:
Thread-1sell99
Thread-1sell98
Thread-1sell97
Thread-1sell96
Thread-1sell95
Thread-1sell94
Thread-1sell93
Thread-1sell92
Thread-1sell91
Thread-1sell90
Thread-1sell89
Thread-1sell88
Thread-1sell87
Thread-1sell86
Thread-1sell85
Thread-1sell84
Thread-1sell83
Thread-1sell82
Thread-1sell81
Thread-1sell80
Thread-1sell79
Thread-1sell78
Thread-1sell77
Thread-1sell76
Thread-1sell75
Thread-1sell74
Thread-1sell73
Thread-1sell72
Thread-1sell71
Thread-1sell70
Thread-1sell69
Thread-1sell68
Thread-1sell67
Thread-1sell66
Thread-1sell65
Thread-1sell64
Thread-1sell63
Thread-1sell62
Thread-1sell61
Thread-1sell60
Thread-1sell59
Thread-1sell58
Thread-0sell57
Thread-0sell56
Thread-0sell55
Thread-0sell54
Thread-0sell53
Thread-0sell52
Thread-0sell51
Thread-0sell50
Thread-0sell49
Thread-0sell48
Thread-0sell47
Thread-0sell46
Thread-0sell45
Thread-0sell44
Thread-0sell43
Thread-0sell42
Thread-0sell41
Thread-0sell40
Thread-0sell39
Thread-1sell38
Thread-1sell37
Thread-1sell36
Thread-1sell35
Thread-1sell34
Thread-1sell33
Thread-1sell32
Thread-1sell31
Thread-1sell30
Thread-1sell29
Thread-1sell28
Thread-1sell27
Thread-1sell26
Thread-1sell25
Thread-1sell24
Thread-1sell23
Thread-1sell22
Thread-1sell21
Thread-1sell20
Thread-1sell19
Thread-1sell18
Thread-1sell17
Thread-1sell16
Thread-1sell15
Thread-1sell14
Thread-1sell13
Thread-1sell12
Thread-1sell11
Thread-1sell10
Thread-1sell9
Thread-1sell8
Thread-1sell7
Thread-1sell6
Thread-1sell5
Thread-1sell4
Thread-1sell3
Thread-1sell2
Thread-1sell1
Thread-1sell0
最后介绍一下线程之间的同步通信问题:
通常会用wait和notify方法
当遇到wait是线程会阻塞,直到遇到同一对象调用的notify方法
下面给出一个实例:
这个例子实现输出一个对象后,等待放入另一个对象后再输出,如此往复
package com.li.example;
/**
此程序实现了线程的同步,考虑到了线程的安全性问题,同时还利用wait()和notify()实现了线程之间的通信问题,
线程的运行机制,虽然启动了一个线程,但不是要完全等待一个线程执行完才执行另外一个线程,而是cpu动态的分配,可能一个线程
正在运行,但cpu将资源分配给了另外一个线程,这就有肯能造成线程的安全性问题,安全性问题可以用synchronized解决
*/
class Q {
private String name = "unknown";
private String sex = "unknown";
private boolean qFull = false;
public synchronized void set(String name, String sex) {
if (qFull)
try {
wait();
}catch(InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
this.name = name;
try {
Thread.sleep(20);
}catch(Exception e) {
}
this.sex = sex;
qFull = true;
notify();
}
public synchronized void get() {
if (!qFull)
try {
wait();
}catch(InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(name);
System.out.println(sex);
qFull = false;
notify();
}
}
class Producer implements Runnable {
Qq = new Q();
public Producer(Q q) {
this.q = q;
}
int i = 0;
public void run() {
while (true) {
if (i == 0)
q.set("li si","female");
else
q.set("zhang san","male");
i = (i + 1) % 2;
}
}
}
class Consumer implements Runnable {
Qq = new Q();
public Consumer(Q q) {
this.q = q;
}
public void run() {
while (true) {
q.get();
}
}
}
class ThreadDemo2 {
static Q q = new Q();
public static void main(String[] args) {
new Thread(new Producer(q)).start();
new Thread(new Consumer(q)).start();
}
}