------- android培训、java培训、期待与您交流! ----------
(一)进程与线程
进程的特征:
1. 一个进程就是一个执行中的程序,而每一个进程都有自己独立的一块内存空间,一组系统资源.在进程概念中,每一个进程的内部数据和状态都是完全独立的
2. 创建并执行一个进程的系统开销是比较大的
3. 进程是程序的一次执行过程,是系统运行程序的基本单位
线程的特征:
1. 在java中,程序通过流控制来执行程序流。程序中单个顺序的流控制称为线程。
2. 多线程则指的是在单个进程中可以同时运行多个不同的线程,执行不同的任务。多线程意味着一个程序的多行语句可以看上去几乎在同一时间内同时运行
不同的是同类的多个线程是共享一块内存空间和一组系统资源,而线程本身的数据通常只有微处理器的寄存器数据,以及一个供程序执行时使用的堆栈
(二)认识线程
A:通过继承Thread类实现多线程
继承Thread类
- 子类覆盖父类中的run方法,将线程运行的代码存放在run中。
- 建立子类对象的同时线程也被创建。
- 通过调用start方法开启线程。
B:通过实现Runnable接口实现多线程
实现Runnable接口
- 子类覆盖接口中的run方法。
- 通过Thread类创建线程,并将实现了Runnable接口的子类对象作为参数传递给Thread类的构造函数。
- Thread类对象调用start方法开启线程。
用Runnable接口来创建线程了。多线程的定义语法如下
class 类名称 implements Runnable //实现Runnable接口
{
属性…
方法…
修饰符 run(){ //覆写Thread类里的run()方法
以线程处理的程序;
}
}
C:这两种方式的联系
Thread 的定义:public class Thread extends Object implements Runnable
Thread 是 Runnable的子类
D:两种方式的区别
使用Thread类在操作多线程的时候无法达到资源共享的目的,而使用Runnable接口
实现的多线程可以实现资源共享;
可分别用一下实例对Thread 和 Runnable进行区别
买火车票时,车票是固定的,但又有多个站点售票:可引出共享的问题
1)用Thread实现多线程
class MyThread extends Thread{ //继承Thread类,作为线程的实现类
private int ticket = 5 ; //表示一共有5张票
public void run(){ //覆写run()方法,作为线程的操作主体
for(int i=0;i<100;i++){
if(this.ticket>0){
System.out.println("卖票:ticket = " + ticket--) ;
}
}
}
};
public class ThreadDemo04{
public static void main(String args[]){
MyThread mt1 = new MyThread() ; //实例化对象
MyThread mt2 = new MyThread() ; //实例化对象
MyThread mt3 = new MyThread() ; //实例化对象
mt1.run() ; //调用线程主体
mt2.run() ; //调用线程主体
mt3.run() ; //调用线程主体
}
};
结果是每个站点(线程)都卖了5张票,不能实现共享
2)用Runnable实现多线程
class MyThread implements Runnable{ //继承Thread类,作为线程的实现类
private int ticket = 5 ; //表示一共有5张票
public void run(){ //覆写run()方法,作为线程的操作主体
for(int i=0;i<100;i++){
synchronized(this){ //要对当前对象进行同步
if(ticket>0){ //还有票
System.out.println("卖票:ticket = " + ticket-- );
}
}
}
}
};
public class RunnableDemo02{
public static void main(String args[]){
MyThread mt = new MyThread() ; //实例化对象
new Thread(mt).start() ; //调用线程主体
new Thread(mt). start() ; //调用线程主体
new Thread(mt). start(); //调用线程主体
}
};
三个站点(线程)一共卖了5张票
(三)线程的状态
任何线程一般具有五种状态,即创建、就绪、运行、阻塞、终止
1. NEW
2. RUNNABLE
3. BLOCKED
4. WAITING
5. TIMED_WAITING
6. TERMINATED
(四)同步(synchronized)
格式:
synchronized(对象)
{
需要同步的代码;
}
同步可以解决安全问题的根本原因就在那个对象上。
该对象如同锁的功能
1.同步的前提:
l 同步需要两个或者两个以上的线程。
l 多个线程使用的是同一个锁。
未满足这两个条件,不能称其为同步。
2.同步的弊端:
当线程相当多时,因为每个线程都会去判断同步上的锁,这是很耗费资源的,无形中会降低程序的运行效率。
3.同步函数
格式:
同步方法定义语法如下
访问控制符 synchronized返回值类型方法名称(参数)
{
…. ;
}
(五)生产者与消费者的案例
生产者要不断生产,但是不能生产错误的信息或重复;消费者要不断取走信息,也不能重复
程序,通过Object类对线程的支持,通过同步,等待,唤醒机制操作对象
class Info{ //定义信息类
private String name = "黑马程序员"; //定义name属性
private String content = "JAVAEE+android" ; //定义content属性
private boolean flag = false ; //设置标志位
public synchronized void set(String name,String content){
if(!flag){
try{
super.wait() ;
}catch(InterruptedException e){
e.printStackTrace() ;
}
}
this.setName(name) ; //设置名称
try{
Thread.sleep(300) ;
}catch(InterruptedException e){
e.printStackTrace() ;
}
this.setContent(content) ; //设置内容
flag = false ; //改变标志位,表示可以取走
super.notify() ;
}
public synchronized void get(){
if(flag){
try{
super.wait() ;
}catch(InterruptedException e){
e.printStackTrace() ;
}
}
try{
Thread.sleep(300) ;
}catch(InterruptedException e){
e.printStackTrace() ;
}
System.out.println(this.getName() +
" --> " + this.getContent()) ;
flag = true ; //改变标志位,表示可以生产
super.notify() ;
}
public void setName(String name){
this.name = name ;
}
public void setContent(String content){
this.content = content ;
}
public String getName(){
return this.name ;
}
public String getContent(){
return this.content ;
}
};
class Producer implements Runnable{ //通过Runnable实现多线程
private Info info = null ; //保存Info引用
public Producer(Info info){
this.info = info ;
}
public void run(){
boolean flag = false ; //定义标记位
for(int i=0;i<50;i++){
if(flag){
this.info.set("黑马程序员","JAVAEE+android") ; //设置名称
flag = false ;
}else{
this.info.set("csdn","www.csdn.net") ; //设置名称
flag = true ;
}
}
}
};
class Consumer implements Runnable{
private Info info = null ;
public Consumer(Info info){
this.info = info ;
}
public void run(){
for(int i=0;i<50;i++){
this.info.get() ;
}
}
};
public class ThreadCaseDemo03{
public static void main(String args[]){
Info info = new Info(); //实例化Info对象
Producer pro = new Producer(info) ; //生产者
Consumer con = new Consumer(info) ; //消费者
new Thread(pro).start() ;
new Thread(con).start() ;
}
};
,
1:wait(),notify(),notifyAll(),用来操作线程为什么定义在了Object类中?
1,这些方法存在与同步中。
2,使用这些方法时必须要标识所属的同步的锁。
3,锁可以是任意对象,所以任意对象调用的方法一定定义Object类中。
2:wait(),sleep()有什么区别?
wait():释放cpu执行权,释放锁。
sleep():释放cpu执行权,不释放锁。