1 进程和线程

进程概述
        什么是进程呢?通过任务管理器我们就可以看到进程的存在。
        概念:进程就是正在运行的程序,是系统进行资源分配和调用的独立单位。每一个进程都有它自己的内存空间和系统资源。

多进程的意义

        单进程计算机只能做一件事情。而我们现在的计算机都可以一边玩游戏(游戏进程),一边听音乐(音乐进程),
        所以我们常见的操作系统都是多进程操作系统。比如:Windows,Mac和Linux等,能在同一个时间段内执行多个任务。
        对于单核计算机来讲,游戏进程和音乐进程是同时运行的吗?不是。
        因为CPU在某个时间点上只能做一件事情,计算机是在游戏进程和音乐进程间做着频繁切换,且切换速度很快,
        所以,我们感觉游戏和音乐在同时进行,其实并不是同时执行的。多进程的作用不是提高执行速度,而是提高CPU的使用率。

线程概述
        在一个进程内部又可以执行多个任务,而这每一个任务我们就可以看成是一个线程。是程序使用CPU的基本单位

多线程的意义

     

并行和并发
        前者是逻辑上同时发生,指在某一个时间内同时运行多个程序。
        后者是物理上同时发生,指在某一个时间点同时运行多个程序。
        并发的关键是你有处理多个任务的能力,不一定要同时。  

        并行的关键是你有同时处理多个任务的能力。

JVM的启动是多线程的吗: 

 *我们启动线程使用不是run方法,而应该是start方法.使该线程开始执行;
         Java 虚拟机调用该线程的 run 方法。

 2 Thread类

java默认是单线程还是多线程 java是单进程还是多进程_多线程

 

public final String getName()//获取线程名称
           public final void setName(String name)//设置线程名称         public static Thread currentThread()//获取当前执行的线程
         public final int getPriority() //获取线程的优先级
        public final void setPriority(int newPriority)//设置线程的优先级,线程的优先级的范围是: 1 - 10
       public static void sleep(long millis) 线程休眠

java默认是单线程还是多线程 java是单进程还是多进程_System_02

       public final void join()   加入线程: 

java默认是单线程还是多线程 java是单进程还是多进程_优先级_03

      public final void stop():        停止线程的运行

java默认是单线程还是多线程 java是单进程还是多进程_java默认是单线程还是多线程_04

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

java默认是单线程还是多线程 java是单进程还是多进程_java默认是单线程还是多线程_05

java默认是单线程还是多线程 java是单进程还是多进程_System_06

      public void interrupt():        中断线程(这个翻译不太好),查看API可得当线程调用wait(),sleep(long time)方法的时候处于阻塞状态,可以通过这个方法清除阻塞

     public final void setDaemon(boolean on):   守护线程,将该线程标记为守护线程或用户线程。当正在运行的线程都是守护线程时,Java 虚拟机退出。 该方法必须在启动线程前调用。

java默认是单线程还是多线程 java是单进程还是多进程_System_07

         

mt1.setDaemon(true) ;//该方法必须在启动线程前调用。
               mt2.setDaemon(true) ;
         
               // 启动线程
              mt1.start() ;
              mt2.start() ;


 

注意事项:  有的时候我们给线程设置了指定的优先级,但是该线程并不是按照优先级高的线程执行,那是为什么呢?
 * 因为线程的优先级的大小仅仅表示这个线程被CPU执行的概率增大了.但是我们都知道多线程具有随机性,
 * 所以有的时候一两次的运行说明不了问题
 

public class MyThread extends Thread {
	
	public MyThread(){}
	
	public MyThread(String name){
		super(name) ;
	}
	
	@Override
	public void run() {
		
		for(int x = 0 ; x < 100 ; x++){

			System.out.println(Thread.currentThread().getName() + "----" + x);
			
		}
		
	}

}
---------------------------------------

// 创建线程对象
		MyThread mt1 = new MyThread("张三") ;
		MyThread mt2 = new MyThread("李四") ;
		
		// public Thread(String name) 给线程设置名称
		
		// 设置名称
		//mt1.setName("张三") ;
		//mt2.setName("李四") ;
		
		// 启动线程
		 mt1.start() ;
		 mt2.start() ;

3  线程安全问题

A:首先想为什么出现问题?(也是我们判断是否有问题的标准)
        是否是多线程环境
        是否有共享数据
        是否有多条语句操作共享数据

B:如何解决多线程安全问题呢?

       把多个语句操作共享数据的代码给锁起来,让任意时刻只能有一个线程执行即可。

 

4  Lock锁

public class MyThread implements Runnable {
	private static int tickets = 100 ;
	private static final Lock lock = new ReentrantLock() ;
	@Override
	public void run() {		
		while(true){
			
			// 添加锁
			lock.lock() ;
			
			if(tickets > 0){				
				try {
					Thread.sleep(100);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}				
				System.out.println(Thread.currentThread().getName() + "正在出售" + (tickets--) + "张票");				
			}			
			// 释放锁
			lock.unlock() ;		
		}	
	}
}

 

5  死锁问题

        如果出现了同步嵌套,就容易产生死锁问题
        是指两个或者两个以上的线程在执行的过程中,因争夺资源产生的一种互相等待现象

锁的概念

在java编程中,经常需要用到同步,而用得最多的也许是synchronized关键字了,
      因为synchronized关键字涉及到锁的概念,所以先来了解一些相关的锁知识。
      java的内置锁:每个java对象都可以用做一个实现同步的锁,这些锁成为内置锁。
      线程进入同步代码块或方法的时候会自动获得该锁,在退出同步代码块或方法时会释放该锁。
      获得内置锁的唯一途径就是进入这个锁的保护的同步代码块或方法。
      java内置锁是一个互斥锁,这就是意味着最多只有一个线程能够获得该锁,
      当线程A尝试去获得线程B持有的内置锁时,线程A必须等待或者阻塞,
      直到线程B释放这个锁,如果B线程不释放这个锁,那么A线程将永远等待下去。
      java的对象锁和类锁:java的对象锁和类锁在锁的概念上基本上和内置锁是一致的,
      但是,两个锁实际是有很大的区别的,对象锁是用于对象实例方法,或者一个对象实例上的,
      类锁是用于类的静态方法或者一个类的class对象上的。
      我们知道,类的对象实例可以有很多个,但是每个类只有一个class对象,
      所以不同对象实例的对象锁是互不干扰的,但是每个类只有一个类锁。
      但是有一点必须注意的是,其实类锁只是一个概念上的东西,并不是真实存在的,
      它只是用来帮助我们理解锁定实例方法和静态方法的区别的.

 

6 总结

三种创建多线程方式

public class Mythread extends Thread {

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(getName()+i);
        }
    }
}
public class Demo1 {
    public static void main(String[] args) {
        Mythread th = new Mythread();
        th.setName("线程A");
        th.start();
    }
}

 

public class Mythread implements Runnable {

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName()+i);
        }
    }
}

public class Demo1 {
    public static void main(String[] args) {
        Mythread th = new Mythread();
        Thread th1 = new Thread(th);
        th1.setName("线程A");
        th1.start();
    }
}

java默认是单线程还是多线程 java是单进程还是多进程_多线程_08

java默认是单线程还是多线程 java是单进程还是多进程_多线程_09

7  编写程序,完成多个窗口共卖100张票的程序,并测试。

方法一

class MyThread extends Thread {
    Object obj = new Object();
    public static int ticket=100;
    public MyThread (String s) {
        super( s );
    }
    public void run() {
        while(true){
            synchronized (obj) {
                if (ticket > 0) {
                    try {
                        Thread.sleep(50);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(getName()+"正在售出第" + (ticket--) + "张票");
                }
            }

        }
    }
}


测试类
class Test {
    public static void main (String[] args) {
        MyThread t1 = new MyThread("线程A");
        MyThread t2 = new MyThread("线程B");
        MyThread t3 = new MyThread("线程C");
        t1.start();
        t2.start();
        t3.start();
    }
}

方法二

class MyThread implements Runnable {
    Object obj = new Object();
     int ticket=100;

    public void run() {
        while(true){
            synchronized (obj) {
                if (ticket > 0) {
                    try {
                        Thread.sleep(50);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+"正在售出第" + (ticket--) + "张票");
                }
            }

        }
    }
}
测试类
class Test {
    public static void main (String[] args) {
        MyThread t1 = new MyThread();
        Thread thread1 = new Thread(t1);
        Thread thread2 = new Thread(t1);
        Thread thread3 = new Thread(t1);
        thread1.setName("A");
        thread2.setName("B");
        thread3.setName("C");
        thread1.start();
        thread2.start();
        thread3.start();
    }
}

 

方法三

class MyThread implements Runnable {
    Object obj = new Object();
     int ticket=100;

    public void run() {
        while(true){
            method();

        }
    }

    private synchronized void method() {

            if (ticket > 0) {
                try {
                    Thread.sleep(50);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"正在售出第" + (ticket--) + "张票");
            }

    }
}

java默认是单线程还是多线程 java是单进程还是多进程_优先级_10

java默认是单线程还是多线程 java是单进程还是多进程_java默认是单线程还是多线程_11