java多线程和高并发

线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位。程序员可以通过它进行多处理器编程,你可以使用多线程对运算密集型任务提速。比如,如果一个线程完成一个任务要100毫秒,那么用十个线程完成改任务只需10毫秒。J

<span style="font-size:18px;">new Thread(){
					public void run() {
					while(true){
						try {
							Thread.sleep(1000);
							System.out.println(Thread.currentThread().getName());
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
						
					}
					
					}
				}.start();</span>

ava 虚拟机允许应用程序并发地运行多个执行线程。

创建新执行线程有两种方法。一种方法是将类声明为 Thread 的子类。该子类应重写Thread 类的run 方法。如下所示:


创建线程的另一种方法是声明实现Runnable 接口的类。该类然后实现 run 方法。然后可以分配该类的实例,在创建 Thread 时作为一个参数来传递并启动。如下所示:

<span style="font-size:18px;">               //直接new runnable接口,实现run方法
		new Thread(new Runnable(){

			public void run() {
				while(true){
					try {
						Thread.sleep(1000);
						System.out.println(Thread.currentThread().getName());
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					
				}
			}
			
		},"second thread").start();</span>
创建线程的操作已经完成,在这里我就要考考大家了,下面代码中哪个线程先执行

<span style="font-size:18px;">                new Thread(new Runnable(){

			public void run() {
				while(true){
					try {
						Thread.sleep(1000);
						System.out.println("1--------------"+Thread.currentThread().getName());
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					
				}
			}
			
		},"second thread"){
			public void run() {
				while(true){
					try {
						Thread.sleep(1000);
						System.out.println("2--------------"+Thread.currentThread().getName());
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					
				}
			}
		}.start();</span>
看到这里的朋友应该有争论了,每个人都有自己的想法。我先来给大家分析一下,1线程是实现Runnable接口,然后有的run方法,2线程是继承thread类,也就继承的是1线程的类,那么2线程重写的也就是2线程的run方法,所以毫无疑问,是线程2重写了线程1,也就是说线程2把线程1给覆盖了,所以只有线程2会执行。

下面我写一个多个线程访问一个方法,产生高并发脏读脏写的简单例子

<span style="font-size:18px;">                final Print print=new Print();
		
		//循环两个线程个一百次
		for(int i=0;i<100;i++){
			new Thread(new Runnable(){

				public void run() {
					while(true){
						try {
							Thread.sleep(200);
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
						print.print("tianwanggaidihu");

						
					}
				}
				
			},"second thread").start();
			
			new Thread(){
				public void run() {
					while(true){
						try {
							Thread.sleep(200);
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
						print.print("baotazhenheyao");
					}
				}
			}.start();
		}
		
	}
	//内部类
	static class Print{
		public synchronized void print(String name){
			// synchronized 互斥锁,多个线程进来的时候保证是同一把锁
			
			for(int i=0;i<name.length();i++){
				//把传进的字符串循环打印
				System.out.print(name.charAt(i));
			}
			System.out.println();
		}
	}</span>
如果我不加互斥锁 synchronized 那么打印出来的字符串会毫无章法,乱七八糟,加上互斥锁的作用就是一个线程访问完另一个才能访问。

多线程有很多很经典的面试题,我给大家整理了两套,先来一个简单的


<span style="font-size:18px;">                   new Thread(new Runnable(){

			public void run() {
				for (int i = 1; i <=30; i++) {
					try {
						Thread.sleep(100);//跑一米需要0.1秒,所以一米让线程休息0.1秒
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					if( i % 10 ==0){
						System.out.println("兔子跑了"+i+"米");
						try {
							Thread.sleep(1000*10);//跑十米休息十秒
						} catch (InterruptedException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					}
				}
				
				
			}
			
		},"rabbit").start();
		
		new Thread(new Runnable(){

			public void run() {
				for (int i = 1; i <=30; i++) {
					
					try {
						Thread.sleep(1000);//跑一米需要一秒,所以一米让线程休息一秒
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					
					if( i % 10==0){
						System.out.println("乌龟跑了"+i+"米");
						try {
							Thread.sleep(1000);//跑十米休息一秒
						} catch (InterruptedException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
						
					}
				}
				
			}
			
		},"turtle").start();</span>
这道题的答案是代表兔子的线程先执行完毕。

子线程循环 10 次,接着主线程循环 5 次,接着又回到子线程循环 10 次,接着再回到主线程循环5次,如此循环5次。参考代码如下:

   <span style="font-size:18px;">              final Service service = new Service();
		//为节省资源,把main当做主线程,为主线程设值
		Thread.currentThread().setName("主线程");
		
		//子线程
		new Thread(new Runnable() {
			public void run() {
				for (int i = 1; i <= 5; i++) {
					try {
						service.sub();
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			}
		}, "子线程").start();
		
		
		for (int i = 1; i <= 5; i++) {
			service.main();
		}
	}

	static class Service {
		//设置一个变量,当前线程是主线程时isMain为true
		boolean isMain = true;
		
		public synchronized void main() throws Exception {
			//当前进来是主线程时让它等待,是子线程时绕过循环继续执行
			while(!isMain){
				this.wait();
			}
			//循环五次
			for (int i = 1; i <= 5; i++) {
				System.out.println("main" + i);
			}
			//主线程执行完,把他变为false
			isMain=false;
			//叫醒子线程
			this.notify();
		}

		public synchronized void sub() throws Exception {
			//当前进来是主线程时让它等待,是子线程时绕过循环继续执行
			if(isMain){
				this.wait();
			}
			//循环十次
			for (int i = 1; i <= 10; i++) {
				System.out.println("sub" + i);
			}
			//子线程执行完,把他变为true
			isMain=true;
			//叫醒主线程
			this.notify();
		}
	}</span>
这就是本人对多线程的理解,本次的分享希望能给大家带来帮助。





  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值