Java线程与进程

进程与线程的关系

  进程里面至少有一个线程,进程间的切换会有较大的开销

  线程必须依附在进程上,同一进程共享代码和数据空间

多线程的优势

  多线程可以达到高效并充分利用cpu

线程使用的方法

继承Thread类使用线程

public class Test{
    public static void main(String[] args){
        MyThread t = new MyThread("x1x");
        t.start();      // 启动线程
    }
}

// 自定义一个类,继承Thread类,重写run()方法
class MyThread extends Thread{
    private Thread thread;
    private String threadName;

    public MyThread(String threadName){
        this.threadName = threadName;
    }

    @override
    public void run(){
        System.out.println("线程名称:" + threadName);
        for(int i = 0; i < 5; i++){
            System.out.println("Thread:" + threadName + "-----" + i);
        }
    }

    public void start(){
        if(null == thread){
            thread = new Thread(this, threadName);
            thread.start();
        }
    }
}    

继承Thread类

实现Runnable接口使用线程 

 public class Test{
     public static void main(String[] args){
         MyRunnable m = new MyRunnable("r1r");
         m.start();
     }
 }

 // 实现Runnable接口,实现run()方法
 class MyRunnable implements Runnable{
     private Thread thread;
     private String threadName;
     // 构造方法
     public MyRunnable(String threadName){
         this.threadName = threadName;
     }

     @override
     public void run(){
         System.out.println("线程名称: " + threadName);
         for(int i = 0; i < 6; i++){
             System.out.println("Thread: " + threadName + "----" + i);
         }
     }

     public void start(){
         if(null == thread){
             thread = new Thread(this, threadName);
             thread.start();
         }
     }
 }

实现Runnable接口

实现Callable接口使用线程

 public class MyCallable implements Callable<Integer>{
     public static void main(String[] args){
         MyCallable mc = new MyCallable();
         // 这里的泛型里面填写的类型也与实现Callable时填写的一致
         FutureTask<Integer> fTask = new FutureTask<>(mc);
         new Thread(fTask, "带返回值的线程").start();
         System.out.println(fTask.get());    // 拿到返回值
     }

     /*
      * call()的返回值类型和实现Callable时填写的类型一致,比如这里是Integer类型,那么
      * call()方法的返回值类型就是Integer类型
     */
     @override
     public Integer  call() throws Exception{
         for(int i = 0; i < 100; i++){
             System.out.println(Thread.currentThread().getName() + "----" + i);
         }
         return i;
     }
 }

实现Callable接口

用匿名内部类的形式使用线程

 public class Test{
     public static void main(String[] args){
         // 利用Thread类实现
         new Thread(){
             @override
             public void run(){
                 while(true){
                     System.out.println(Thread.currentThread().getName());
                 }
             }
         }.start();

         // 利用Runnable接口实现
         new Thread(new Runnable(){
             @override
             public void run(){
                 while(true){
                     System.out.println(Thread.currentThread().getName());
                 }
             }
         }).start();
     }
 }

内部类形式调用

继承Runnable和Callable接口比继承Thread类的优势

  • 适合多个相同的程序代码的线程去处理同一个资源
  • 可以避免java中的单继承的限制
  • 增加程序的健壮性,代码可以被多个线程共享,代码和数据独立

线程的优先级

java中的线程是具有优先级的,优先级高的线程会获得更多的运行机会。

java中线程的优先级是用整数来表示的,取值范围是1 - 10

Thread类中有三个静态常量表示优先级:

  static int MAX_PRIORITY   线程可以具有的最高优先级,取值为10

  static int MIN_PRIORITY    线程可以具有的最低优先级,取值为1

  static int NORM_PRIORITY  分配给线程的默认优先级,取值为5

如果要对线程设置优先级或者获取线程的优先级,可以使用Thread类的setPriority 和 getPriority方法分别得到和获取

线程的常用方法

  sleep()     强迫线程睡眠

  join()        等待线程终止

  currentThread()    得到当前方法所在的线程

  isDaemon()    一个线程是否为守护线程

  setDaemon()    设置一个线程为守护线程

  setName()      为线程设置名称

  wait()      强迫线程等待

  interrupt()    终止线程

  notify()  notifyAll()   通知线程继续执行

  setPriority()     设置优先级

  getPriority()     获取优先级

同步

使用synchronized同步锁

  1. 获得同步锁
  2. 清空工作内存
  3. 从主内存拷贝对象到工作内存
  4. 刷新主内存
  5. 释放同步锁
 /*
  * 这个程序的本意是第一个线程先输出zhangsan,然后第二个线程输出lisi
  * 但是由于两个线程同步执行,第一个线程调用output()方法还未结束,第二个线程就已
  *经开始调用output()方法
  * 最终的输出就会是zlhiasnigsan
  * 就好比两个工人在同一时间使用同一机器加工零件,那不就乱套了吗?
  */

 public class synchronizedTest {
     public static void main(String[] args) {
         final Outputter o = new Outputter();
         new Thread() {
             public void run() {
                 o.output("zhangsan");
             }
         }.start();
         new Thread(new Runnable() {

             @Override
             public void run() {
                 // TODO Auto-generated method stub
                 o.output("lisi");
             }
         }).start();
     }
 }

 class Outputter{
     // 放在代码块前面
     public void output(String name) {
         for(int i = 0; i < name.length(); i++) {
             System.out.print(name.charAt(i));
             try {
                 Thread.sleep(1000);
             } catch (InterruptedException e) {
                 // TODO Auto-generated catch block
                 e.printStackTrace();
             }
         }
     }
 }

没有同步带来的问题

 /*
  * 在要调用的output()方法前面加上synchronized同步锁就可以解决上述问题
  * 当使用同步锁后,同一对象在同一时间只允许一个线程使用
  * 也就是说,第一个线程调用output()方法,在进入方法后,synchronized就
  * 上锁了,后面的线程就不能调用了,必须等待当前线程执行完output()方法释放锁后
  * 后面的线程才允许调用
  * 就好比第一个工人要开始使用机器加工零件了,在使用机器前,他将房门锁住了,于是
  * 后面
  * 的工人便不能进房间使用机器,必须等工人一加工完零件,将锁打开,第二个工人才能
  * 进去
  * 加工零件
  */

 public class synchronizedTest {
     public static void main(String[] args) {
         final Outputter o = new Outputter();
         new Thread() {
             public void run() {
                 o.output("zhangsan");
             }
         }.start();
         new Thread(new Runnable() {

             @Override
             public void run() {
                 // TODO Auto-generated method stub
                 o.output("lisi");
             }
         }).start();
     }
 }

 class Outputter{
     // 放在代码块前面
     public synchronized void output(String name) {
         for(int i = 0; i < name.length(); i++) {
             System.out.print(name.charAt(i));
             try {
                 Thread.sleep(1000);
             } catch (InterruptedException e) {
                 // TODO Auto-generated catch block
                 e.printStackTrace();
             }
         }
     }
 }

使用同步解决问题1

 /*
  * 第二种使用synchronized的方法就是将synchronized
  * 放在要上锁的代码块前面,原理与上述一致
  */

 public class synchronizedTest {
     public static void main(String[] args) {
         final Outputter o = new Outputter();
         new Thread() {
             public void run() {
                 o.output("zhangsan");
             }
         }.start();
         new Thread(new Runnable() {

             @Override
             public void run() {
                 // TODO Auto-generated method stub
                 o.output("lisi");
             }
         }).start();
     }
 }

 class Outputter{
     public void output(String name) {
         // 放在代码块前面
         synchronized(this) {
             for(int i = 0; i < name.length(); i++) {
                 System.out.print(name.charAt(i));
                 try {
                     Thread.sleep(1000);
                 } catch (InterruptedException e) {
                     // TODO Auto-generated catch block
                     e.printStackTrace();
                 }
             }
         }
     }
 }

使用同步锁解决问题2

synchronized(){

}的括号里面放的是需要互斥的对象,就是两个工人加工零件使用的同一个机器

使用volatile同步变量

volatile使变量对线程具有可见性

java线程与进程的更多相关文章

  1. JAVA线程和进程区别

    1,JAVA线程和进程区别? (1)简单来讲一个运行的程序就是一个进程,一个进程中可以有多个线程(线程是程序执行的最小单元). (2)线程有四种状态:运行,就绪,挂起,结束 (3)使用多线程的好处 使 ...

  2. Java线程和进程相关面试题与答案总结

    有几天没有写一写博客了,今天就带给大家一些面试题和参考答案吧! 这些都是上海尚学堂Java培训的学员去面试时遇到的问题,今天总结出来的是Java线程相关类的面试题.把参考答案和解析也发布出来,供大家学 ...

  3. 关于java线程、进程的一些问题

    1.多核硬件上,java中同一个进程的多个线程可以运行在不同的CPU上么? 应该是可以的,在eclipse上面跑一个模拟程序,一个死循环的线程可以占用系统(4核,Win7)%的CPU,4个这样的线程刚 ...

  4. Java线程和进程

    一.线程 1.什么是线程: 线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.一个进程至少包含一个线程,也可以多个,线程属于进程. 2.Java中线程经历的四个 ...

  5. java线程,进程,多线程

    (1)线程和进程 通俗一点,进程就是一个应用程序在处理机上的一次执行过程,它是一个动态的概念,而线程是进程中的一部分,进程包含多个线程在运行. (2)java中实现线程的两种方式,第一种是继承Thre ...

  6. 菜鸡的Java笔记 第三十七 - java 线程与进程

    线程与进程        线程与进程的区别                最早的的时候DOS 系统有一个特点:只要电脑有病毒,那么电脑就死机了,是因为传统的DOS 系统属于单进程的操作系统       ...

  7. java线程与进程的比较

    线程具有许多传统进程所具有的特征,故又称为轻型进程(Light—Weight Process)或进程元:而把传统的进程称为重型进程(Heavy—Weight Process),它相当于只有一个线程的任 ...

  8. java线程基础梳理

    java线程 概述 进程:运行时概念,运行的应用程序,进程间不能共享内存 线程:应用程序内并发执行的代码段,可以共享堆内存和方法区内存,而栈内存是独立的. 并发理解:在单核机器上,从微观角度来看,一段 ...

  9. Java中的进程和线程

     Java中的进程与线程 一:进程与线程 概述:几乎任何的操作系统都支持运行多个任务,通常一个任务就是一个程序,而一个程序就是一个进程.当一个进程运行时,内部可能包括多个顺序执行流,每个顺序执行流就是 ...

随机推荐

  1. Python内置函数(59)——open

    英文文档: open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, ope ...

  2. SiteMesh入门(1-1)SiteMesh是什么?

    1.问题的提出 在开发Web 应用时,Web页面可能由不同的人参与开发,因此开发出来的界面通常千奇百怪.五花八门,风格难以保持一致. 为了统一界面的风格,Struts 框架提供了一个标签库Tiles ...

  3. 查看eclipse ADT SDK JDK版本号

    一.查看eclipsea版本号: 启动eclipse,Help > About Eclipse SDK,在eclipse SDK对话框下面就有Eclipse SDK Version:4.2.0这 ...

  4. 转:swing 中paint与paintComponent的区别(jcomponent)

    http://blog.csdn.net/q597756870/article/details/17854247 查API文档,查得在类Jcomponent下的paint方法有以下解释:        ...

  5. Codeforces Round #441 (Div. 2, by Moscow Team Olympiad) A. Trip For Meal

    http://codeforces.com/contest/876/problem/A 题意: 一个人一天要吃n次蜂蜜,他有3个朋友,他第一次总是在一个固定的朋友家吃蜂蜜,如果说没有吃到n次,那么他就 ...

  6. 框架学习笔记之Mybatis(二)

    一.动态sql 通过mybatis提供的标签,实现sql语句的拼接. 1.where <select id="findUserList" parameterType=&quo ...

  7. ZOJ-1649 Rescue---BFS+优先队列

    题目链接: https://vjudge.net/problem/ZOJ-1649 题目大意: 天使的朋友要去救天使,a是天使,r 是朋友,x是卫兵.每走一步需要时间1,打倒卫兵需要另外的时间1,问救 ...

  8. 如何在Shell读取文件并赋值

    sys_info=$(cat /usr/local/sysconfig.txt)var=`echo   $sys_info   |   awk   -F ', '   '{print   $0} '  ...

  9. 10_Python函数方法加深_Python编程之路

    上节课已经简单的跟大家讲了如何定义一个方法,但是并没有深入去讲,这一节我们继续来学习定义方法中需要注意的几点 默认参数 前面我们讲到定义一个方法时是可以传递参数的,除了这个功能,实际上python在定 ...

  10. 高并发下,log4j日志打印行数导致的内存溢出问题

    log4j日志打印时,如果将行数打印出来,在调用量极大的情况下,会出现内存溢出问题. log4j打印日志,打印行数时,行数是通过一个一个exception抛出,再极高调用量的情况下,内存会因为exce ...