Java多线程

首先 理解进程的概念,在操作系统中一个程序的 执行周期就称为一个进程。在最初的DOS操作系统由于其本身只是一个单进程的系统,所以在同一时间段只能执行一个程序,而后来windows可以执行多进程,这样一块资源在同一时间段会有多个进程交替执行,但是在同一个时间点只会有一个时间点去执行。

而线程是在进程上面的进一步划分,线程是比进程更小的单位。Java本身是一个多线程的语言,多线程引用体现在哪里呢?

所谓高并发就是访问的线程 爆高



Java多线程的实现

前提:有一个线程的执行主类

用户----》主类main方法------》多线程主类,我们主要考虑 的就是多线程主类的定义结构,现在有两种方式可以实现这个主类,第一种继承Thread类,第二种是实现Runnable或Callable接口

1.Thread实现

package com.wjx.sayHello;

class myThread extends Thread{

	private String name;
	public myThread(String name){
		this.name=name;
	}
	@Override
	public void run(){
		for(int x=0;x<10;x++){
			System.out.println(name+",x="+x);
		}
	}
}




public class TestDemo {
	
	public static void main(String[] args){
		myThread m1=new myThread("A");
		myThread m2=new myThread("B");
		myThread m3=new myThread("C");
		m1.start();
		m2.start();
		m3.start();
		
	}
}

启动多线程public void start(),调用此方法虚拟机会调用run()方法,对象直接调用run()方法没有意义,那为啥呢?看看源码

2.Runnable接口

 Thread  和 Runnable 的关系:public class Thread extends Object implements Runnable

package com.wjx.sayHello;

class myThread implements Runnable{

	private String name;
	public myThread(String name){
		this.name=name;
	}
	@Override
	public void run(){
		for(int x=0;x<10;x++){
			System.out.println(name+",x="+x);
		}
	}
}





public class TestDemo {
	
	public static void main(String[] args){
		myThread m1=new myThread("A");
		myThread m2=new myThread("B");
		myThread m3=new myThread("C");
//		m1.start();
//		m2.start();
//		m3.start();
		new Thread(m1).start();
		new Thread(m2).start();
		new Thread(m3).start();
		
	}
}

3.通过callable

jdk1.5之后追加了一个开发包Java,util.concurrent,这个开发包主要提供一些高并发的类。

由于Runnable 的run()方法也是线程的主方法,但是没有返回值,当线程执行完成带来一些返回值的时候我们这个时候就需要使用Callable来实现多线程

package com.wjx.sayHello;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

class myThread implements Callable<String>{

	@Override
	public String call() throws Exception {
		for(int x=0;x<10;x++){
			System.out.println("x="+x);
		}
		return "票卖完了";
	}
	
}
public class TestDemo {
	
	public static void main(String[] args) throws InterruptedException, ExecutionException{
		FutureTask<String> ft=new FutureTask<String>(new myThread());
		new Thread(ft).start();
		System.out.println(ft.get());
			
		
		
	}
}

4.多线程的常用操作方法

(1)线程的命名和取得

package com.wjx.sayHello;
class myThread implements Runnable{
	@Override
	public void run() {
		for(int x=0;x<10;x++){
			System.out.println("线程名字是:"+Thread.currentThread().getName()+",x的值是:"+x);
		}	
	}	
}
public class TestDemo {
	
	public static void main(String[] args){
		myThread mt=new myThread();
		//Thread(Runnable target, String name)构造方法,返回name值
		new Thread(mt, "Leo").start();//
		new Thread(mt).start();//自动命名,比如Thread-0
		mt.run();//返回main,主方法本身是一个线程
		
	}
}

(2)线程休眠

public static void sleep(long millis) throws InterruptedException

package com.wjx.sayHello;
class myThread implements Runnable{
	@Override
	public void run() {
		for(int x=0;x<10;x++){
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println("线程名字是:"+Thread.currentThread().getName()+",x的值是:"+x);
		}	
	}	
}
public class TestDemo {
	
	public static void main(String[] args){
		myThread mt=new myThread();
		//Thread(Runnable target, String name)构造方法,返回name值
		new Thread(mt, "Leo").start();//
		new Thread(mt).start();//自动命名,比如Thread-0
		mt.run();//返回main,主方法本身是一个线程
		
	}
}


3.线程优先级

package com.wjx.sayHello;
class myThread implements Runnable{
	@Override
	public void run() {
		for(int x=0;x<2;x++){
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println("线程名字是:"+Thread.currentThread().getName()+",x的值是:"+x);
		}	
	}	
}
public class TestDemo {
	
	public static void main(String[] args){
		//获取主方法的优先级,为NORM_PRIORITY 返回是5
		System.out.println(Thread.currentThread().getPriority());
		myThread mt=new myThread();
		Thread t1=new Thread(mt,"ThreadA");
		Thread t2=new Thread(mt,"ThreadB");
		Thread t3=new Thread(mt,"ThreadC");
		// 设置优先级,只是有可能优先执行,并不一定啊
		t1.setPriority(Thread.MIN_PRIORITY); //MIN_PRIORITY 常量1
		t2.setPriority(Thread.NORM_PRIORITY);//MIN_PRIORITY 常量5
		t3.setPriority(Thread.MAX_PRIORITY);//MIN_PRIORITY 常量10
		
		t1.start();
		t2.start();
		t3.start();
		
		
		
	
		
		
	}
}

4 线程的同步和死锁

同步问题的引出:观察一个不同步的问题

package com.wjx.sayHello;
class myThread implements Runnable{
	private int ticket=10;
	@Override
	public void run() {
		for(int x=0;x<20;x++){
			
			if(ticket>0){
				try {
					Thread.sleep(1000);//延迟暴露问题,同步会造成当几个进程同时判断票数>0都满足的同时,由于延迟,ticket--还没有操作,如果此时其他进来,票数可能小于0
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				System.out.println("售票员名字是:"+Thread.currentThread().getName()+",票数剩余是:"+ticket--);
			}
		}	
	}	
}
public class TestDemo {
	
	public static void main(String[] args){
		//获取主方法的优先级,为NORM_PRIORITY 返回是5

		myThread mt=new myThread();
		Thread t1=new Thread(mt,"张三");
		Thread t2=new Thread(mt,"李四");
		Thread t3=new Thread(mt,"王五");
		
		
		t1.start();
		t2.start();
		t3.start();
//执行结果:
//		售票员名字是:张三,票数剩余是:10
//		售票员名字是:李四,票数剩余是:9
//		售票员名字是:王五,票数剩余是:8
//		售票员名字是:张三,票数剩余是:7
//		售票员名字是:李四,票数剩余是:6
//		售票员名字是:王五,票数剩余是:5
//		售票员名字是:张三,票数剩余是:4
//		售票员名字是:李四,票数剩余是:3
//		售票员名字是:王五,票数剩余是:2
//		售票员名字是:张三,票数剩余是:1
//		售票员名字是:李四,票数剩余是:0
//		售票员名字是:王五,票数剩余是:-1
//结论:不同步数据的访问是不安全的

			
		
	}
}

如何处理:同步处理:所有线程不是一起进入方法,而是按照顺序一步一步进入。当一个程序进入一个方法的时候,上把锁,不解锁,其他进程无法进入,我们使用Synchronized来处理,有两种方式,同步代码块,同步方法。同步虽然保证数据的完整性,但是访问速度变慢了。

1...同步代码块(必须要设置一个被锁定的对象,一般锁定当前对象)

package com.wjx.sayHello;
class myThread implements Runnable{
	private int ticket=10;
	@Override
	public void run() {
		for(int x=0;x<20;x++){
			synchronized(this){
			if(ticket>0){
				try {
					Thread.sleep(1000);//延迟暴露问题,同步会造成当几个进程同时判断票数>0都满足的同时,由于延迟,ticket--还没有操作,如果此时其他进来,票数可能小于0
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				System.out.println("售票员名字是:"+Thread.currentThread().getName()+",票数剩余是:"+ticket--);
			}
			}
		}	
	}	
}
public class TestDemo {
	
	public static void main(String[] args){
		//获取主方法的优先级,为NORM_PRIORITY 返回是5

		myThread mt=new myThread();
		Thread t1=new Thread(mt,"张三");
		Thread t2=new Thread(mt,"李四");
		Thread t3=new Thread(mt,"王五");
		t1.setPriority(Thread.MIN_PRIORITY);
		t2.setPriority(Thread.MAX_PRIORITY);
		t3.setPriority(Thread.NORM_PRIORITY);
		
		t1.start();
		t2.start();
		t3.start();
//执行结果
//		售票员名字是:王五,票数剩余是:10
//		售票员名字是:王五,票数剩余是:9
//		售票员名字是:王五,票数剩余是:8
//		售票员名字是:张三,票数剩余是:7
//		售票员名字是:李四,票数剩余是:6
//		售票员名字是:李四,票数剩余是:5
//		售票员名字是:李四,票数剩余是:4
//		售票员名字是:李四,票数剩余是:3
//		售票员名字是:李四,票数剩余是:2
//		售票员名字是:李四,票数剩余是:1

		
		
	
		
		
	}
}

2...同步方法
package com.wjx.sayHello;
class myThread implements Runnable{
	private int ticket=10;
	@Override
	public void run() {
		sale();
	}	
	public synchronized void sale(){
		for(int x=0;x<20;x++){
			
			if(ticket>0){
				try {
					Thread.sleep(1000);//延迟暴露问题,同步会造成当几个进程同时判断票数>0都满足的同时,由于延迟,ticket--还没有操作,如果此时其他进来,票数可能小于0
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				System.out.println("售票员名字是:"+Thread.currentThread().getName()+",票数剩余是:"+ticket--);
			}
			
		}	
	}
}
public class TestDemo {
	
	public static void main(String[] args){
		//获取主方法的优先级,为NORM_PRIORITY 返回是5

		myThread mt=new myThread();
		Thread t1=new Thread(mt,"张三");
		Thread t2=new Thread(mt,"李四");
		Thread t3=new Thread(mt,"王五");
		t1.setPriority(Thread.MIN_PRIORITY);
		t2.setPriority(Thread.MAX_PRIORITY);
		t3.setPriority(Thread.NORM_PRIORITY);
		
		t1.start();
		t2.start();
		t3.start();


		
		
	
		
		
	}
}

3死锁(同步带来的问题)

模拟一个死锁 ,下面是一个死锁程序,程序造成死锁

package com.wjx.sayHello;
class Pen{
	public synchronized void get(){
		System.out.println("获取笔记本");
	}
	public synchronized void getOther(Book book){
		System.out.println("获取其他,book");
		book.get();
	}
}
class Book{
	public synchronized void get(){
		System.out.println("获取笔");
	}
	public synchronized void getOther(Pen pen){
		System.out.println("获取其他,pen");
		pen.get();
	}
}
public class DeadLock implements Runnable{
	Pen pen =new Pen();
	Book book=new Book();
	public static void main(String[] args) {
		new DeadLock();
	}
	public DeadLock(){
		new Thread(this).start();
		pen.getOther(book);
	}
	@Override
	public void run() {
		book.getOther(pen);
	}

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值