进程是应用程序的执行实例。
进程是程序的一次动态执行过程,它经历了从代码加载、执行到执行完毕的一个完整过程,这个过程也是进程本身从产生、发展到最终消亡的过程特征:动态产生,动态消亡。进程是并发性的。进程独立性。是一个独立运行的基本单位,也是系统分配资源和调度的基本单位1.2、线程多线程是实现并发机制的一种有效手段。进程和线程一样,都是实现并发的一个基本单位线程:进程内部的一个执行单元,它是程序中一个单一的顺序控制流程特点:使用步骤:
定义一个线程----创建线程的实例--启动线程--终止线程
2.1、继承Thread类Thread类是在java.lang包中定义的,一个类只要继承了Thread类,此类就称为多线程操作类。在Thread子类之中,必须明确的覆写Thread类中的run()方法,此方法为线程的主体
/** * 继承Thread类重写run方法 * */public class MyThead1 extends Thread { PRivate int count; @Override public void run() { System.out.println("=======线程启动了======="); while(this.count<100){ count++; } System.out.println("count最终的值:"+count); } public int getCount() { return count; } public void setCount(int count) { this.count = count; } }
测试类
/** * 测试类 * MyTheadDemo * 继承Thread类创建线程 * 1.继承Thread类 * 2.重写run方法 * 3.实例化线程类对象 * 4.调用start方法启动线程 * * 继承Thread类存在问题 * Java中是单继承的,线程类不能继承其它的类 * * 解决办法:实现Runnable接口 * */public class MyTheadDemo1 { public static void main(String[] args) { //实例化线程类对象 MyThead1 myThead1=new MyThead1(); //启动线程 myThead1.start(); /* * start方法的作用 * 该方法公使操作系统初始化一个新的线程 * 由这个新线程来执行线程对象的Run方法 */ }}2.2、实现Runnable接口(推荐使用,使用接口可以解决Java中单继承的问题)在Java中也可以通过实现Runnable接口的方式实现多线程,Runnable接口中只定义了一个抽象方法:public void run() ;
/** * 实现Runnable接口 * */public class MyRunnable implements Runnable { private int count; @Override public void run() { System.out.println("=======线程启动了======="); while(this.count<100){ count++; } System.out.println("count最终的值:"+count); } public int getCount() { return count; } public void setCount(int count) { this.count = count; } }
测试类
/** * 测试类 * MyRunnable * 实现Runnable接口创建线程 * 1.实现Runnable接口 * 2.实现run方法 * 3.实例化线程类对象 * 4.创建Thread类实例对象,并将实例化的线程对象传入 * 5.调用Thread类实例对象的start方法启动线程 * */public class MyRunnableDemo { public static void main(String[] args) { //实例化线程类对象 Runnable myRunnable=new MyRunnable(); Thread thread=new Thread(myRunnable); //或者Thread thread=new Thread(new MyRunnable()); //启动线程 thread.start(); }}2.3、启动线程
/** * 实现Runnable接口 * */public class MyRunnable implements Runnable { private int count; @Override public void run() { count++; System.out.println("count最终的值:"+count); } public int getCount() { return count; } public void setCount(int count) { this.count = count; } }
测试类
/** * 测试类 * MyRunnable * 实现Runnable接口创建线程 * 1.实现Runnable接口 * 2.实现run方法 * 3.实例化线程类对象 * 4.创建Thread类实例对象,并将实例化的线程对象传入 * 5.调用Thread类实例对象的start方法启动线程 * */public class MyRunnableDemo { public static void main(String[] args) { //实例化线程类对象 Runnable myRunnable=new MyRunnable(); Thread thread=new Thread(myRunnable); Thread thread2=new Thread(myRunnable); //或者Thread thread=new Thread(new MyRunnable()); //启动线程 System.out.println("线程1启动"); thread.start(); System.out.println("线程2启动"); thread2.start(); }}
结果:
线程1启动线程2启动count最终的值:1count最终的值:2
再看下thread方式
/** * 继承Thread类重写run方法 * */public class MyThead1 extends Thread { private int count; @Override public void run() { count++; System.out.println("count最终的值:"+count); } public int getCount() { return count; } public void setCount(int count) { this.count = count; } }
/** * 测试类 * MyTheadDemo * 实现Runnable接口创建纯种 * 1.实现Runnable接口 * 2.重写run方法 * 3.实例化线程类对象 * 4.调用start方法启动线程 * * 继承Thread类存在问题 * Java中是单继承的,线程类不能继承其它的类 * * 解决办法:实现Runnable接口 * */public class MyTheadDemo1 { public static void main(String[] args) { //实例化线程类对象 MyThead1 myThead1=new MyThead1(); MyThead1 myThead2=new MyThead1(); //启动线程 System.out.println("线程1启动"); myThead1.start(); System.out.println("线程2启动"); myThead2.start(); /* * start方法的作用 * 该方法公使操作系统初始化一个新的线程 * 由这个新线程来执行线程对象的Run方法 */ }}
结果:
线程1启动线程2启动count最终的值:1count最终的值:1三、线程的状态要想实现多线程,必须在主线程中创建新的线程对象。任何线程一般具有五种状态,即创建、就绪、运行、阻塞、终止。四、线程的优先级和方法4.1、线程的优先级
4.2、线程的方法
No. | 方法名称 | 类型 | 描述 |
1 | public Thread(Runnable target) | 构造 | 接收Runnable接口子类对象,实例化Thread对象 |
2 | public Thread(Runnable target,String name) | 构造 | 接收Runnable接口子类对象,实例化Thread对象,并设置线程名称 |
3 | public Thread(String name) | 构造 | 实例化Thread对象,并设置线程名称 |
4 | public static Thread currentThread() | 普通 | 返回目前正在执行的线程 |
5 | public final String getName() | 普通 | 返回线程的名称 |
6 | public final int getPriority() | 普通 | 发挥线程的优先级 |
7 | public boolean isInterrupted() | 普通 | 判断目前线程是否被中断,如果是,返回true,否则返回false |
8 | public final boolean isAlive() | 普通 | 判断线程是否在活动,如果是,返回true,否则返回false |
9 | public final void join() throws InterruptedException | 普通 | 等待线程死亡 |
10 | public final synchronized void join(long millis) throws InterruptedException | 普通 | 等待millis毫秒后,线程死亡 |
11 | public void run() | 普通 | 执行线程 |
12 | public final void setName(String name) | 普通 | 设定线程名称 |
13 | public final void setPriority(int newPriority) | 普通 | 设定线程的优先值 |
14 | public static void sleep(long millis) throws InterruptedException | 普通 | 使目前正在执行的线程休眠millis毫秒 |
15 | public void start() | 普通 | 开始执行线程 |
16 | public static void yield() | 普通 | 将目前正在执行的线程暂停,允许其它线程执行 |
17 | public final void setDaemon(boolean on) | 普通 | 将一个线程设置成后台运行 |
18 | public final void setPriority(int newPriority) | 普通 | 更改线程的优先级 |
作用:阻塞指定的线程等到另一个线程完成以后,再继续执行
package thead;/** * 实现join方法 * 1.join的线程运行完成后,才会继承运行当前线程 * 2.join之前要先启动线程start方法 * */public class JoinRunnable implements Runnable { @Override public void run() { for (int i = 0; i <5; i++) { System.out.println(Thread.currentThread().getName()+" 第"+i+"次"); } } public static void main(String[] args) { //主线程 for (int i = 0; i <10; i++) { if(i==5){ Thread thread=new Thread(new JoinRunnable());; thread.setName("半路切入的线程:"); try { //启动线程 thread.start(); //半路加入线程 thread.join(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(Thread.currentThread().getName()+" 第"+i+"次"); } }}
结果:
main 第0次main 第1次main 第2次main 第3次main 第4次半路切入的线程: 第0次半路切入的线程: 第1次半路切入的线程: 第2次半路切入的线程: 第3次半路切入的线程: 第4次main 第5次main 第6次main 第7次main 第8次main 第9次5.2、sleep()阻塞当前线程,当前等待的线程将获得机会
调用sleep方法后,,当前线程会被扶起(暂停执行)当前线程会释放资源
package thead;public class SleepRunnable implements Runnable { @Override public void run() { try { for (int i = 0; i < 10; i++) { //每一秒执行一次 Thread.sleep(1000); System.out.println(Thread.currentThread().getName()+i); } } catch (InterruptedException e) { e.printStackTrace(); } } public static void main(String[] args) { Thread sleepThread=new Thread(new SleepRunnable()); sleepThread.setName("等待中的线程"); sleepThread.start(); for (int i = 0; i < 10; i++) { if(i==5){ try { //主线程=等5秒 Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(Thread.currentThread().getName()+i); } } }
结果:
main0main1main2main3main4等待中的线程0等待中的线程1等待中的线程2等待中的线程3main5main6main7main8main9等待中的线程4等待中的线程5等待中的线程6等待中的线程7等待中的线程8等待中的线程95.3、yield()方法
将当前线程转入可运行状态,
package yield;/** * 线程一 * */public class MyThread1 implements Runnable { @Override public void run() { for (int i = 0; i <10; i++) { Thread.yield(); System.out.println(Thread.currentThread().getName()+":"+i); } }}package yield;/** * 线程二 * */public class MyThread2 implements Runnable { @Override public void run() { for (int i = 0; i <10; i++) { Thread.yield(); System.out.println(Thread.currentThread().getName()+": "+i); } }}package yield;/** * yield方法使用 *2个线程抢占方式 */public class Test { public static void main(String[] args) { Thread myThread1=new Thread(new MyThread1()); myThread1.setName("线程1"); Thread myThread2=new Thread(new MyThread2()); myThread2.setName("线程2"); //同时启动2个线程 myThread1.start(); myThread2.start(); }}
结果:
线程2: 0线程1:0线程2: 1线程1:1线程2: 2线程1:2线程2: 3线程1:3线程1:4线程2: 4线程1:5线程1:6线程1:7线程1:8线程1:9线程2: 5线程2: 6线程2: 7线程2: 8线程2: 9
sleep()和yield()方法比较
将线程设置 为后台线程(守护线程)。
只能在线程启动之前设置.
package thead;public class Daemon implements Runnable { @Override public void run() { for (int i = 0; i <10; i++) { System.out.println(Thread.currentThread().getName()+":"+i); } } public static void main(String[] args) { Thread daemon=new Thread(new Daemon()); daemon.setName("后台线程"); // 设置为后台线程 daemon.setDaemon(true); daemon.start(); for (int i = 0; i <10; i++) { System.out.println(Thread.currentThread().getName()+":"+i); } }}六、同步一个多线程的程序,如果是通过Runnable接口实现的,则意味着类中的属性将被多个线程共享,那么这样一来就会造成一种问题,如果这多个线程要操作同一资源的时候就有可能出现资源的同步问题。例如:以之前的卖票程序来讲,如果多个线程同时操作的时候就有可能出现卖出票为负数的问题。问题的解决如果想解决这样的问题,就必须使用同步,所谓的同步就是指多个操作在同一个时间段内只能有一个线程进行,其他线程要等待此线程完成之后才可以继续执行解决资源共享的同步操作,可以使用同步代码块和同步方法两种方式完成同步代码块在代码块上加上“synchronized”关键字的话,则此代码块就称为同步代码块。同步方法除了可以将需要的代码设置成同步代码块之外,也可以使用synchronized关键字将一个方法声明成同步方法。同步方法定义格式:synchronized 方法返回值 方法名称(参数列表){}6.1、简单例子
同一账户2个人同时取款
package demo;public class Account { //余额 private int balance=500; //检查余额 public int getBalance() { return balance; } //取款 public void withDraw(int amount){ balance=balance-amount; } public void setBalance(int balance) { this.balance = balance; } }package demo;public class TestAccount implements Runnable{ private Account account=new Account(); @Override public void run() { for (int i = 0; i <5; i++) { //一次取走100 makeWithDraw(100); if(account.getBalance()<0){ System.out.println("账户透支了!!!!!"); } } } //取款参数 同步方法 private synchronized void makeWithDraw(int amount){ if(account.getBalance()>=amount){ //当前余额是否足够可以取款 System.out.println(Thread.currentThread().getName()+" 准备取款"); try { //0.5秒后取款 Thread.sleep(500); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } //完成取款 account.withDraw(amount); System.out.println(Thread.currentThread().getName()+" 完成取款,当前余额为: "+account.getBalance()); }else{ //如果余额不足不能取款 System.out.println(Thread.currentThread().getName()+" 余额不足以支付当前取款, 余额为: " +account.getBalance()); } } }
测试类
package demo;/** * 如果一个资源被多个线程使用,不上锁就会造成读取严重错误 * 如果想让当前资源被一个线程使用时,不会受到其他纯种的影响,应该给当前资源上锁 * Java中使用sychronized关键字保证数据同步 * */public class Test { public static void main(String[] args) { //创建线程类的实例 TestAccount ta=new TestAccount(); //创建线程 Thread thread1=new Thread(ta); thread1.setName("张三"); Thread thread2=new Thread(ta); thread2.setName("张三的妻子"); //启动线程 thread1.start(); thread2.start(); }}
上面是同步方法
下面是同步代码块
package demo;public class TestAccount implements Runnable{ private Account account=new Account(); @Override public void run() { for (int i = 0; i <5; i++) { //一次取走100 makeWithDraw(100); if(account.getBalance()<0){ System.out.println("账户透支了!!!!!"); } } } //取款参数 private void makeWithDraw(int amount){ //同步代码块 synchronized (account){ if(account.getBalance()>=amount){ //当前余额是否足够可以取款 System.out.println(Thread.currentThread().getName()+" 准备取款"); try { //0.5秒后取款 Thread.sleep(500); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } //完成取款 account.withDraw(amount); System.out.println(Thread.currentThread().getName()+" 完成取款,当前余额为: "+account.getBalance()); }else{ //如果余额不足不能取款 System.out.println(Thread.currentThread().getName()+" 余额不足以支付当前取款, 余额为: " +account.getBalance()); } } } }七、线程间通信的实现
以上3个方法只能在同步方式或者同步代码块中使用
wait()方法:会挂起当前的线程,并且释放共享资源的锁。当前线程会从可运行状态转为阻塞状态直到调用了wait()方法所属的那个对象的notify()方法或者notifyAll()方法.
notify()方法:可以唤醒因为调用wait()方法而被挂起的那个线程,并且使这个线程退出阻塞状态进入可运行状态
notifyAll()方法:可以唤醒因为所有调用wait()方法而被挂起的那个线程,并且使这些线程退出阻塞状态进入可运行状态
生产者和消费者package com.pb;/** * 商品共享数据 * */public class SharedData { private char c; private boolean idProducted=false;//信号量 //同步方法生产者生产产品的的方法 public synchronized void putSharedChar(char c){ //如果产品还没有被消费,则生产都等待 if(idProducted){ try { System.out.println("消费者还未消费,因此生产都停止生产"); wait(); } catch (InterruptedException e) { e.printStackTrace(); } } this.c=c; idProducted=true; //标记已经生产 notify();//通知消费都 System.out.println("生产者生产了产品"+c+",通知消费者"); } //同步方法 消费者消费产品的的方法 public synchronized char getSharedChar(char c){ //如果产品还没有被消费,则生产都等待 if(idProducted==false){ try { System.out.println("生产者还未生产,消费者停止消费"); wait(); } catch (InterruptedException e) { e.printStackTrace(); } } idProducted=false; //标记已经消费 notify();//通知生产者 System.out.println("消费者消费了产品"+c+",通知生产者"); return this.c; }}
package com.pb;/** * 生产者 * */public class Producer implements Runnable { //共享数据 private SharedData sharedData; public Producer(SharedData sharedData){ this.sharedData=sharedData; } @Override public void run() { for (char c = 'A'; c <= 'D'; c++) { try { Thread.sleep((int)Math.random()*3000); } catch (InterruptedException e) { e.printStackTrace(); } //将产品生产后,放入仓库 sharedData.putSharedChar(c); } }}
package com.pb;/** * 消费者 * */public class Consumer implements Runnable { //共享数据 private SharedData sharedData; public Consumer(SharedData sharedData){ this.sharedData=sharedData; } @Override public void run() { char ch = 0; do { try { Thread.sleep((int)Math.random()*3000); } catch (InterruptedException e) { e.printStackTrace(); } //从仓库中取中产品 ch=sharedData.getSharedChar(ch); } while (ch!='D'); }}
测试类
package com.pb;public class CommunicationDemo { public static void main(String[] args) { //共享资源,产品 SharedData sharedData=new SharedData(); Thread producer=new Thread(new Producer(sharedData)); Thread consumer=new Thread(new Consumer(sharedData)); //启动线程 consumer.start(); producer.start(); }}
结果:
生产者还未生产,消费者停止消费生产者生产了产品A,通知消费者消费者消费了产品A,通知生产者生产者生产了产品B,通知消费者生产者还未生产,消费者停止消费生产者生产了产品C,通知消费者消费者消费了产品B,通知生产者生产者生产了产品D,通知消费者消费者消费了产品C,通知生产者
新闻热点
疑难解答