实现线程的方式是一,继承Thread类,重写父类的run()方法
二,实现接口Runnable中的run()方法。
下面是简单的例子
例子1:银行存取钱问题
package com.direct.demo;
public class Bank {
private static int money;
public int getMoney(){
return money;
}
public void saveMoney( int m){
synchronized ( this ) {
System.out.println( "存钱后的总金额:" +(money+=m));
}
}
public void drawMoney( int m){
synchronized ( this ) {
Bank bank = new Bank();
if (bank.getMoney()<= 0 ) {
System.out.println( "没得钱,取个pi" );
} else {
System.out.println( "取钱后剩的总金额:" +(money-=m));
}
}
}
public static void main(String[] args) {
Man m1 = new Man();
Women w = new Women();
Thread t1 = new Thread(m1);
Thread t2 = new Thread(m1);
Thread t3 = new Thread(m1);
Thread t4 = new Thread(w);
Thread t5 = new Thread(w);
Thread t6 = new Thread(w);
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
t6.start();
}
}
class Man implements Runnable{
private Bank bank = new Bank();
public void run() {
int m = 100 ;
int i= 0 ;
while (i< 5 ) {
bank.saveMoney(m);
i++;
try {
Thread.sleep( 100 );
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Women implements Runnable{
private Bank bank = new Bank();
public void run() {
int m = 100 ;
int i= 0 ;
//bank.getMoney()>0
while (i< 5 ) {
bank.drawMoney(m);
try {
Thread.sleep( 100 );
} catch (InterruptedException e) {
e.printStackTrace();
}
i++;
}
}
}
例子2:生产者与消费者问题
package com.direct.demo;
public class Clerk {
private int product = - 1 ;
//这个方法由生产者调用
public synchronized void setProduct( int product){
if ( this .product != - 1 ) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this .product = product;
System.out.printf( "生产者设定 (%d)%n" , this .product);
notify();
}
//这个方法由消费者调用
public synchronized int getProduct(){
if ( this .product==- 1 ) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
int p = this .product;
System.out.printf( "消费者取走 (%d)%n" , this .product);
this .product = - 1 ;
notify();
return p;
}
public static void main(String[] args) {
Clerk clerk = new Clerk();
new Thread( new ProducerInt(clerk)).start();
new Thread( new ConsumerInt(clerk)).start();
}
}
class ProducerInt implements Runnable{
private Clerk clerk;
public ProducerInt(Clerk clerk){
this .clerk = clerk;
}
public void run() {
System.out.println( "生产者开始生产整数了.................." );
for ( int product = 1 ; product <= 10 ; product++) {
try {
Thread.sleep(( int )Math.random()* 300 );
} catch (InterruptedException e) {
e.printStackTrace();
}
clerk.setProduct(product);
}
}
}
class ConsumerInt implements Runnable{
private Clerk clerk;
public ConsumerInt(Clerk clerk){
this .clerk = clerk;
}
public void run() {
System.out.println( "消费者开始消耗整数........" );
for ( int i = 1 ; i <= 10 ; i++) {
try {
Thread.sleep(( int )Math.random()* 300 );
} catch (InterruptedException e) {
e.printStackTrace();
}
clerk.getProduct(); //从店员取走整数
}
}
}
例子3:购票窗口实现票数同步
package com.direct.demo;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ThreadTicket {
public static void main(String[] args) {
Booking b1 = new Booking( "军人售票口" );
Booking b2 = new Booking( "学生售票口" );
Booking b3 = new Booking( "老年人售票口" );
Booking b4 = new Booking( "网上售票口" );
b1.start();
b2.start();
b3.start();
b4.start();
}
}
/*
* 多窗口卖票系统。多线程
* 票数为静态的,共享数据
* synchronized(对象){}代码块中的内容是加锁的,
* 即当一个线程在使用时,其他线程不可以进入。
* 使得共享资源数据的安全。
*/
class Booking extends Thread{
public Booking(String name){
super (name);
}
static int ticket = 50 ; //票数共50张
Lock lock = new ReentrantLock(); //明锁
/*
* ReentrantLock根据传入构造方法的布尔型参数实例化出Sync的实现类FairSync和NonfairSync
* ,分别表示公平的Sync和非公平的Sync。
* 由于ReentrantLock我们用的比较多的是非公平锁
ReentrantLock 和synchronized 均为重入锁
* 1. ReenTrantLock可以指定是公平锁还是非公平锁。而synchronized只能是非公平锁。所谓的公平锁就是先等待的线程先获得锁。
2. ReenTrantLock提供了一个Condition(条件)类,用来实现分组唤醒需要唤醒的线程们,而不是像synchronized要么随机唤醒一个线程要么唤醒全部线程。
3. ReenTrantLock提供了一种能够中断等待锁的线程的机制,通过lock.lockInterruptibly()来实现这个机制。
对ReentrantLock的可重入锁这篇博客使用简单的例子进行讲解, http://blog.csdn.net/yanyan19880509/article/details/52345422
* Lock是个接口,只能实例化它的子类
* 明锁适合高并发,上万
* 暗锁适合并发率不高时,效率高
*/
//重写run方法,
public void run(){
while (ticket> 0 ){
synchronized (Booking. class ) {
if (ticket> 0 ) {
System.out.println( super .getName()+ "窗口---->卖出的车票号No." +ticket);
ticket--;
} else {
System.out.println( super .getName()+ "票已售罄!!!" );
}
try {
sleep( 100 ); //睡100毫秒,抛出多线程异常
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/*lock.lock();//加锁,锁定以下代码
if (ticket>0) {
System.out.println(super.getName()+"卖票:"+ticket);
ticket--;
}else {
System.out.println(super.getName()+"票已售罄!!!");
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
lock.unlock();//解锁
*/ }
}
}
例子4:线程中sleep()和wait()方法测试
package com.direct.demo;
public class TestSleepaWait {
public static void main(String[] args) {
new Thread( new Thread1()).start();
try {
Thread.sleep( 5000 );
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread( new Thread2()).start();
}
}
class Thread1 implements Runnable{
public void run() {
synchronized (TestSleepaWait. class ) {
System.out.println( "Thread1 is start........" );
System.out.println( "Thread1 is wait.............." );
try {
//调用wait方法,线程会放弃对象锁,进入等待对象的等待锁定池
TestSleepaWait. class .wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println( "Thread1 is go on........" );
System.out.println( "Thread1 is over!" );
}
}
}
class Thread2 implements Runnable{
@Override
public void run() {
synchronized (TestSleepaWait. class ) {
System.out.println( "Thread2 is enter.........." );
System.out.println( "Thread2 is sleep......." );
//只有针对对象调用notify()方法后本线程才进入对象锁定池
//准备获取对象进入运行状态
TestSleepaWait. class .notify();
//===============
//如果把上句注释掉。即对象锁调用了wait方法,但是没有调用notify
//程序就一致处于挂起状态
try {
Thread.sleep( 5000 );
//sleep方法暂停执行时间,让出CPU,监控状态保持,
//时间到 了就回复运行, 不会释放对象锁
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println( "Thread2 is going on.........." );
System.out.println( "Thread2 is over!!!!" );
}
}
}
例子5:sleep()实现对象存取值
package com.direct.demo;
public class ThreadCom {
public static void main(String[] args) {
Person person = new Person();
new Thread( new Producer(person)).start();
new Thread( new Consumer(person)).start();
}
}
class Person{
private String name = "张杰" ;
private String sex = "男" ;
public synchronized void put(String name,String sex){
this .name = name;
this .sex = sex;
try {
Thread.sleep( 100 );
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//方法加锁
public synchronized void get(){
System.out.println(name+ "----->" +sex);
try {
Thread.sleep( 100 );
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class Consumer implements Runnable{
Person person;
public Consumer(Person person){
this .person = person;
}
public void run() {
while ( true ){
person.get();
}
}
}
class Producer implements Runnable{
Person person;
public Producer(Person person){
this .person = person;
}
public void run() {
int i = 0 ;
while ( true ) {
if (i== 0 ) {
person.put( "谢娜" , "女" );
} else {
person.put( "张杰" , "男" );
}
i = (i+ 1 )% 2 ; //奇数和偶数
}
}
}
例子6:死锁发生条件
在写代码时要避免死锁
package com.direct.demo;
public class DeadLock {
public static void main(String[] args) {
ThreadLock tl = new ThreadLock( true );
ThreadLock tl2 = new ThreadLock( false );
new Thread(tl).start();
new Thread(tl2).start();
}
}
/*
* 死锁的产生条件:
* 1、至少一个资源共享
* 2、至少有一个线程(任务),必须持有资源,且等待获取别的线程持有的资源
* 3、任务抢不到资源
* 4、必须有无限循环
* (1) 互斥条件:一个资源每次只能被一个进程使用。
* (2) 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
* (3) 不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。
* (4) 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
* 举例说明:不可剥夺资源A、B,进程C、D
* 不可剥夺资源:一个进程申请了之后,不能强制收回,只能进程结束之后自动释放。内存是可剥夺资源
* 进程C申请了资源A,进程D申请了资源B。
* 接下来进程C的操作需要用到资源B,进程D的操作需要用到资源A
* 但是C、D都得不到资源,就引发了死锁
*/
class Lock{
static Object lockOne = new Object(); //资源A
static Object lockTwo = new Object(); //资源B
}
class ThreadLock implements Runnable{
private boolean flag;
public ThreadLock( boolean flag){
this .flag = flag;
}
@Override
public void run() {
if (flag){
while ( true ) {
synchronized (Lock.lockOne) {
System.out.println( " this is lockOne" );
synchronized (Lock.lockTwo) {
System.out.println( "this is lockTwo" );
}
}
}
} else {
while ( true ) {
synchronized (Lock.lockTwo) {
System.out.println( " 这是 lockTwo" );
synchronized (Lock.lockOne) {
System.out.println( "这是 lockOne" );
}
}
}
}
}
}