java 多线程

                                                            java 多线程

进程的特点有:

                    ->进程是系统运行程序的基本单位

                    ->进程都有一个自己独立的,一块内存空间和一组系统资源

                    ->进程的内部数据和状态都是独立的

多线程的优点:

                           1.CPU的资源利用率强

                           2.简化编程模型

                           3.程序响应速度快

CPU的资源利用强在那

        就是在磁盘读取一个文件所需5秒,处理一个文件所需2秒

处理两个文件则需要:


        磁盘在读取文件的时候,这时CPU处于空闲时间。这样可以让CPU做点事情,通过在同一时间让读取和处理一起进行。

这样更好的利用的CPU资源!


CPU等待磁盘读取完第一个文件,然后开始读取第二个文件。当第二文件在被读取的时候,CPU会去处理第一个文件。

这样可以有效的利用CPU资源。

        总的说,例如手下有两个人,A员工的工作是搬货,B员工的工作是拆货,让A员工搬货,但A员工搬货搬到让B员工进行拆箱这样就实现了节省时间。如果B员工等A员工搬完货在拆箱,这样他们完成工作时间就会比前一种说话多。

简化编程模型

       在单线程应用程序中,如果你想编写程序手动处理上面所提到的读取和处理的顺序,你必须记录每个文件读取和处理的状态。相反,你可以启动两个线程,每个线程处理一个文件的读取和操作。线程会在等待磁盘读取文件的过程中被阻塞。在等待的时候,其他的线程能够使用CPU去处理已经读取完的文件。磁盘总是在繁忙地读取不同的文件到内存中。这会带来磁盘和CPU利用率的提升。而且每个线程只需要记录一个文件,因此这种方式也很容易编程实现。

程序响应速度快

       单线程应用程序变成多线程应用程序的另一个常见的目的是实现一个响应更快的应用程序。假设一个服务器应用,它在某一个端口监听进来的请求。当一个请求到来时,它去处理这个请求,然后再返回去监听。

服务器的流程如下所述:

如果一个请求需要占用大量的时间来处理,在这段时间内新的客户端就无法发送请求给服务端。只有服务器在监听的时候,请求才能被接收。另一种设计是,监听线程把请求传递给工作者线程(worker thre90ad),然后立刻返回去监听。而工作者线程则能够处理这个请求并发送一个回复给客户端。这种设计如下所述:


这种方式,服务端线程迅速地返回去监听。因此,更多的客户端能够发送请求给服务端。这个服务也变得响应更快。


Thread类中的常用方法

            Thread()  分配新的Thread对象

            Thread(Runnable target)  分配新的Thread对象,target为run()方法被调用的对象

            Thread(Runnable target,string name) 

            分配新的Thread对象,target为run()方法被调用的对象,name为新线程的名称

            void run()执行任务操作的方法

            void start () 使该线程开始执行,Java虚拟机调用线程的run()方法

            void sleep()在指定的毫秒数内让当前正在执行的线程休眠(暂停执行)

            String getName()返回线程的名称

            int getPriority()返回线程的优先级

            void getPriority(int newPriority)更改线程的优先级

            static Thread currentThread()返回当前正在执行的线程对象的引用

            boolean isAlive()测试线程是否处于活动状态

            void jion()等待该线程终止

            void interrupt()中断线程

            void yield() 暂停当前正在执行的线程对象,并执行其他线程

getName 和 setName 使用

public class MyThread {
	public static void main(String[] args) {
		//获取主线程对象
		Thread t = Thread.currentThread();
		//用getname 获取线程名
		System.out.println("当前线程是"+t.getName());
		//用setname 修改线程名
		t.setName("MyThread");
		//用getname 获取线程名
		System.out.println("当前线程是"+t.getName());
	}

}

继承Thread类创建线程过程

    1.继承Thread类

    2.重写run()方法

    3.创建线程对象,调用start()方法执行线程

    启动一个线程代码如下:

import entity.MyThread2;


public class Thread2 {
	public static void main(String[] args) {
		//创建MyThread2对象
		MyThread2 t = new MyThread2();
		//启动线程
		t.start();
	}

}

package entity;

public class MyThread2 extends Thread {
	public void run(){
		//重写Run
		for (int i = 1; i < 100; i++) {
			System.out.println(Thread.currentThread().getName()+" "+i);
		}
	}

}

    启动多个线程代码如下

import entity.MyThread2;


public class Thread2 {
	public static void main(String[] args) {
		//创建MyThread2对象
		MyThread2 t = new MyThread2();
		//启动线程
		t.start();
		//第二个线程
		//创建MyThread2对象
		MyThread2 t2 = new MyThread2();
		//启动线程
		t2.start();
	}

}
package entity;

public class MyThread2 extends Thread {
	public void run(){
		//重写Run
		for (int i = 1; i < 100; i++) {
			System.out.println(Thread.currentThread().getName()+" "+i);
		}
	}

}

多个线程运行过程 ,个个线程会交替执行!

如果启动线程直接调用run()方法,它只有主线程一条执行路径。

调用start()方法,多条执行路径,主线程和子线程并行交替执行!

 

实现Runnable接口创建线程

public class MyRunnable implements Runnable{
	//实现Runnable接口创建线程
	//重写Run
	public void run(){		
		for (int i = 1; i < 100; i++) {
			System.out.println(Thread.currentThread().getName()+" "+i);
		}
	}


}
public class test {
	public static void main(String[] args) {
		//创建runnable 实现对象
		Runnable myrunnable = new MyRunnable();
		//创建线程对象
		Thread t = new Thread(myrunnable);
		//启动线程
		t.start();
	}
}

在Thread 对象中改线程名


public class test {
	public static void main(String[] args) {
		//创建runnable 实现对象
		Runnable myrunnable = new MyRunnable();
		//创建线程对象
		Thread t = new Thread(myrunnable,"myRunnable");
		//启动线程
		t.start();
	}
} 

    Thread类和Runnable接口

     继承Thread类

    1.编写简单,可直接操作线程

    2.适用于单继承

    实现Runnable接口

    1.避免单继承的局限性

    2.便于共享资源

                                                                            线程的状态




                                       //线程的状态
public class MyRunnable implements Runnable{
	//重写Run
	public void run(){		
		System.out.println("线程正在运行!");
		try {
			//线程休眠   必须放到Try中
			Thread.sleep(500);
			System.out.println("线程休眠,处于阻塞状态");
		} catch (InterruptedException e) {
			e.printStackTrace();
			System.out.println("线程被中断");
		}
	}
	public static void main(String[] args) {
		Thread t = new Thread(new MyRunnable(),"线程");
		System.out.println("线程处于创建线程状态");
		t.start();
		System.out.println("线程处于就绪状态");
	}
}

                                           线程调度   常用方法

setPriority(int newpriority)     更改线程的优先级

static void sleep(long millis)    在指定的毫秒数内让当前正在执行的线程休眠

void join () 等待该线程终止

static void yield() 暂停当前正在执行的线程对象,并执行其他线程

void interrupt()中断线程

Boolean isAlive()测试线程是否处于活动状态

                                         线程的优先级

代码如下:
public class MyRunnable implements Runnable{
	public void run(){
		//重写Run
		for (int i = 1; i < 100; i++) {
			System.out.println(Thread.currentThread().getName()+" "+i);
		}
	}
}
public class test {
	public static void main(String[] args) {
		//创建线程对象
		Thread t1 = new Thread(new MyRunnable(),"线程A");
		Thread t2 = new Thread(new MyRunnable(),"线程B");
		//设置优先级
		t1.setPriority(Thread.MAX_PRIORITY);
		t2.setPriority(Thread.MIN_PRIORITY);
		//启动线程
		t1.start();
		t2.start();
	}
}

                                                 线程的休眠

代码如下:

public class Wait {
	public static void bySec(long s) {
		//每次循环休眠1秒
		for (int i = 0; i < s; i++) {
			System.out.println(i+1+"秒");
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}
public class test {
	public static void main(String[] args) {
		System.out.println("-------主线程开始休眠-------");
		//让主线程休眠5秒
		Wait.bySec(5);
		System.out.println("-------主线程休眠结束-------");
	}
}

                                                               线程的强制运行

使当前线程暂停执行,等待其他线程结束后再继续执行本线程

public final void join()  public final void join(long mills) public final void join(long mill,int nanos) 三种方法
             

                millis:以毫秒为单位的等待时间

                nanos:要等待的附加纳秒时间

                需处理InterruptedException异常

代码如下:

public class MyThread  extends Thread {
	public void run(){
		for (int i = 1; i < 10; i++) {
			try {
				Thread.sleep(100);//每次休眠0.1秒
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName()+"运行:"+i);
		}
	}
}
public class test {
	public static void main(String[] args) {
		System.out.println("-----------线程强制执行-----------");
		//创建线程对象
		Thread T = new MyThread();
		T.setName("thread");
		//启动线程
		T.start();
		for (int i = 1; i < 20; i++) {
			if (i==5) {
				try {
					//需要异常
					T.join();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName() +"运行" + i);
		}
	}
}
                                                                     线程的礼让

public static void yield()

暂停当前线程,允许其他具有相同优先级的线程获得运行机会

该线程处于就绪状态,不转为阻塞状态

只是提供一种可能,但是不能保证一定会实现礼让

代码如下:

public class MyRunnable implements Runnable{
	public void run(){
		//重写Run
		for (int i = 0; i < 5; i++) {
			System.out.println(Thread.currentThread().getName()+"运行 "+i);
			//当i==3  执行线程礼让,当前线程将cpu资源让出
			if (i==3) {
				//线程礼让
				Thread.yield();
				System.out.println("线程礼让:");
			}
			try {
				//进行休眠 交替执行,提高可能性
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}
public class test {
	public static void main(String[] args) {
		Thread t1 = new Thread(new MyRunnable(),"线程A");
		Thread t2 = new Thread(new MyRunnable(),"线程B");
		t1.start();
		t2.start();
	}
}

                                                 同步方法和同步代码块

同步方法关键字:synchronized

同步方法的使用,代码如下:

public class MyRunnable implements Runnable{
	private int count = 10;//记录票数
	private int num = 0;//记录当前抢到第几张票
	private boolean flag = false;//记录票是否卖完
	public void run() {
		while (!flag) {
			sale();
		}
	}
	public synchronized void sale(){
		if (count<=0) {
			flag = true;
			return;
		}
		//修改数据
		count--;
		num++;
		try {
			Thread.sleep(500);//演示网络延迟
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println(Thread.currentThread().getName()+"抢到第"+num+"张票,剩余"+count+"张票");
	}
}
public class test {
	public static void main(String[] args) {
		MyRunnable  Runnable = new MyRunnable();
		Thread t1 = new Thread(Runnable,"A");
		Thread t2 = new Thread(Runnable,"B");
		Thread t3 = new Thread(Runnable,"C");		
		t2.start();
		t3.start();
		t1.start();
	}
}

同步代码,代码如下:
public class MyRunnable implements Runnable {
	private int count = 10;// 记录票数
	private int num = 0;// 记录当前抢到第几张票
	private boolean flag = false;// 记录票是否卖完

	public void run() {
		while (!flag) {
			synchronized (this) {
				if (count <= 0) {
					flag = true;
					return;
				}
				// 修改数据
				count--;
				num++;
				try {
					Thread.sleep(500);// 演示网络延迟
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println(Thread.currentThread().getName() + "抢到第"
						+ num + "张票,剩余" + count + "张票");
			}
		}
	}

}

public class test {
	public static void main(String[] args) {
		MyRunnable  Runnable = new MyRunnable();
		Thread t1 = new Thread(Runnable,"A");
		Thread t2 = new Thread(Runnable,"B");
		Thread t3 = new Thread(Runnable,"C");		
		t2.start();
		t3.start();
		t1.start();
	}
}

为达到安全性和效率的平衡,可以根据实际场景来选择合适的类型。

                                                             死锁

   死锁---------两个线程都在等待对方先完成,造成程序的停滞

     死锁的条件

            两个或者两个以上的线程在活动

            某个线程拿到一个锁以后,还想拿第二个锁,造成锁的嵌套

模拟死锁代码如下:

package entity;
/**
 * 模拟死锁
 * @Liang
 *
 */
public class test{
	public static void main(String[] args) {
		Object bobby = new Object();//芭比
		Object duck = new Object();//玩具鸭
		Thread t1 = new Thread(new doudou(bobby,duck));
		Thread t2 = new Thread(new tangtang(bobby,duck));
		t1.start();
		t2.start();
	}

}
class doudou implements Runnable{
	Object bobby;//芭比
	Object duck;//玩具鸭
	public void run() {
		synchronized (bobby) {
			try {
				Thread.sleep(500);
			} catch (Exception e) {
				e.printStackTrace();
			}
			synchronized (duck) {
				
			}
			System.out.println("豆豆吧玩具鸭给糖糖玩了");
		}
	}
	public doudou(Object bobby, Object duck) {
		super();
		this.bobby = bobby;
		this.duck = duck;
	}
}
class tangtang implements Runnable{
	Object bobby;//芭比
	Object duck;//玩具鸭
	public void run() {
		synchronized (duck) {
			try {
				Thread.sleep(500);
			} catch (Exception e) {
				e.printStackTrace();
			}
			synchronized (bobby) {
				
			}
			System.out.println("糖糖吧玩具鸭给豆豆玩了");
		}
	}
	public tangtang(Object bobby, Object duck) {
		super();
		this.bobby = bobby;
		this.duck = duck;
	}
}

                                                   线程池

线程的缺点           

            占用过多系统资源

            缺少更多功能,如定时执行,定期执行等

使用线程池的好处

         重用存在的线程,减少对象创建,消亡的开销

            有效控制最大的并发数,提高系统资源使用率

            定时执行,定期执行

线程池API

       线程池所在包 java.util.concurrent

       顶级接口是Executor,真正的线程池接口是ExecutorService

       java.util.concurrent.Executors类提供创建线程池的方法

   线程池方法有

newCachedThreadPool()   创建一个可缓存的线程池,有任务时才创建新任务

newSingleThreadExecutor() 创建一个单线程池

newFixedThreadPool(int nThreads) 创建一个固定长度的线程池,空闲线程会一只保留。参数nThread设定线程池中线程的数目

newScheduledThreadPool(int corePoolSize) 创建了一个固定长度的线程池,而且以延迟或定时的方式来执行任务

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值