Java学习之多线程

 

1.进程和线程的区别:

简单的说,一个程序至少有一个进程,一个进程至少有一个线程,线程的划分尺度小于进程,使得多线程程序的并发性高;
另外,进程在执行过程中拥有独立的内存单元,而多线程共享内存,从而极大提高了程序的运行效率;
线程是进程的一个实体,是CPU调度和分派的基本单元,比进程更小的能独立运行的基本单位;一个线程可以创建和撤销另一个线程;同一个进程中的多个线程可以并发行;

比较:

单线程实例:

它总是按照顺序执行,当方法的调用,转而执行其它方法,完成再回来执行原方法;

public class test{
public static void main(string args[]){
	m1();
}
public static void m1(){
	m2();
	m3();
}
public static void m2(){}
public static void m3(){}
}

多线程实例:使两个进程同时进行,即并发执行;

public class TestThread {
	public static void main(String[] args) {
		myRunnable rMyRunnable=new myRunnable();
		Thread thread=new Thread(rMyRunnable);
		thread.start();
		for (int i = 0; i < 50; i++) {
			System.out.println("mainThread:"+i);
		}
	}
}
class myRunnable implements Runnable {
	public void run() {
		for (int i = 0; i < 50; i++) {
			System.out.println("myRunnable:"+i);
		}
	}
}


 

2.启动线程的两种方式:
第一种:实现Runnable接口
第二种:定义一个类继承Thread类。

举一个实现Runnable接口的实现线程的方式:

public class TestThread {
	public static void main(String[] args) {
		myRunnable rMyRunnable=new myRunnable();
		rMyRunnable.start();
		for (int i = 0; i < 50; i++) {
			System.out.println("mainThread:"+i);
		}
	}
}
class myRunnable extends Thread {
	public void run() {
		for (int i = 0; i < 50; i++) {
			System.out.println("myRunnable:"+i);
		}
	}
}


 

3.Thread中的方法:
start():使该线程开始执行;Java 虚拟机调用该线程的 run 方法。

sleep():让当前执行的线程沉睡一定的时间;简单的时钟来解释这个sleep()方法和start()方法;

public class TestThread {
	public static void main(String[] args) {
		myRunnable rMyRunnable=new myRunnable();
		rMyRunnable.start();
}
}
class myRunnable extends Thread {
	public void run() {
		while (true) {
		System.out.println("现在时间:"+new Date());
		try {
			sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		}
}
}


4.线程同步问题:
问题:多个线程同时访问同一个资源;
解决的办法:当一个先程访问该资源的时候,不允许其它线程去访问该资源;
synchronized(this){}锁定当前对象,则在一个线程进行时,禁止其它线程来访问;
例子:

public class TestThread implements Runnable{
	Test test=new Test();
	public static void main(String[] args) {
		TestThread testThread=new TestThread();
		//启动同一个线程
		Thread t1=new Thread(testThread);
		Thread t2=new Thread(testThread);
		t1.setName("t1");
		t2.setName("t2");
		t1.start();
		t2.start();
	}
	@Override
	public void run() {
		//得到当前线程的名字,传给add()方法;
		test.add(Thread.currentThread().getName());
	}
}
class Test{
	private static int num=0;
	public void add(String  name){
		//加上同步锁,保证同一时间只有一个线程可以访问该资源,锁定当前对象;
		synchronized (this) {
		num++;
		try {
			Thread.sleep(1);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println(name+"你是第"+num+"个访问此资源的");
		}
	}
}


 

举个简单的小例子:数据库中有一条数据,现在又两个方法,一个读数据,一个改数据,那么在该数据的方法上加上同步锁,禁止同时修改数据,但没必要在读数据的方法上加同步锁,可以同时访问。

5.经典的生产者和消费者的问题:

举例:厨司生产馒头,馒头放入篮子中,消费者从篮子中取出馒头吃,这个过程;

public class Test {
	public static void main(String[] args) {
		LanZi lz=new LanZi();
		Producer p=new Producer(lz);
		Consumer c=new Consumer(lz);
		new Thread(p).start();
		new Thread(c).start();
	}
}
//定义馒头类
class ManTou {
	private int id;
	public ManTou(int id) {
		this.id = id;
	}
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	//重写 toString方法
	  public String  toString() {
		   return "第"+id+"个馒头";
	}
}
//定义篮子类
class LanZi {
	int index=0;
	//分配数组空间
	ManTou[] arrManTous=new ManTou[6];
	//放馒头进去方法,加锁锁定资源,保证不能多线程同时访问;
	public synchronized void push(ManTou mt){
		if (index==arrManTous.length) {
			try {
				//访问当前对象的线程等待;wait()是object的方法;
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		//唤醒等待的线程;
		this.notify();
		arrManTous[index]=mt;
		index++;
	}
	//取馒头出来方法,加锁锁定资源,保证不能多线程同时访问;
	public synchronized ManTou pop(){
		if (index==0) {
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		this.notify();
		index--;
		return arrManTous[index];
	}
}
//定义生产者类
class Producer implements Runnable {
	LanZi lz=null;
	Producer(LanZi lz){
		this.lz=lz;
	}
	@Override
	public void run() {
		for (int i = 0; i < 20; i++) {
			ManTou mt=new ManTou(i);
			lz.push(mt);
			System.out.println("生产了:"+mt);
			try {
				Thread.sleep((long) (Math.random()*30));
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}
//定义消费者类
class Consumer implements Runnable {
	LanZi lz=null;
	Consumer(LanZi lz){
		this.lz=lz;
	}
	@Override
	public void run() {
		for (int i = 0; i < 20; i++) {
			ManTou mt=lz.pop();
			System.out.println("消费了:"+mt);
			try {
				Thread.sleep((long) (Math.random()*3000));
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}





 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值