Java实现给图片添加图片水印,文字水印及马赛克的方法示例

本文实例讲述了Java实现给图片添加图片水印,文字水印及马赛克的方法。分享给大家供大家参考,具体如下:

可以在eclipse中新建个Utils类,把以下代码复制进去直接使用,以下方法实现单个或多个水印的添加

package com.rzxt.fyx.common.util;
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
/**
 * 给图片添加水印
 * @author tgy
 *
 */
public class MarkImageUtils {
  /**
   * @param args
   */
  public static void main(String[] args) {
  String output = "F:/images/";
    String source = "F:/images/6.jpg";  //源图片路径
    String icon = "F:/images/icon2.png"; //覆盖图片路径
    String imageName = "mark_image"; //图片名称
    String imageType = "jpg"; //图片类型jpg,jpeg,png,gif
    String text = "加水印了";
    int size = 4;  //马赛克大小
    Integer degree = null; //水印旋转角度-45,null表示不旋转
    String result = null;
    //给图片添加图片水印
    result = MarkImageUtils.markImageByMoreIcon(icon,source,output,imageName,imageType,degree);
//    result = MarkImageUtils.markImageBySingleIcon(icon, source, output, imageName, imageType, degree);
//    //给图片添加文字水印
//    result = MarkImageUtils.markImageByMoreText(source,output,imageName,imageType,Color.red,text,degree);
//    result = MarkImageUtils.markImageBySingleText(source,output,imageName,imageType,Color.red,text,degree);
//    //给图片打马赛克
//    result = MarkImageUtils.markImageByMosaic(source,output,imageName,imageType,size);
    System.out.println(result);
  }
/**
   * 给图片不同位置添加多个图片水印、可设置水印图片旋转角度
   * @param icon 水印图片路径(如:F:/images/icon.png)
   * @param source 没有加水印的图片路径(如:F:/images/6.jpg)
   * @param output 加水印后的图片路径(如:F:/images/)
   * @param imageName 图片名称(如:11111)
   * @param imageType 图片类型(如:jpg)
   * @param degree 水印图片旋转角度,为null表示不旋转
   */
  public static String markImageByMoreIcon(String icon,String source,String output,String imageName,String imageType,Integer degree) {
    String result = "添加图片水印出错";
    try {
    File file = new File(source);
    File ficon = new File(icon);
    if (!file.isFile()) {
      return source + " 不是一个图片文件!";
    }
      //将icon加载到内存中
      Image ic = ImageIO.read(ficon);
      //icon高度
      int icheight = ic.getHeight(null);
      //将源图片读到内存中
      Image img = ImageIO.read(file);
      //图片宽
      int width = img.getWidth(null);
      //图片高
      int height = img.getHeight(null);
      BufferedImage bi = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
      //创建一个指定 BufferedImage 的 Graphics2D 对象
      Graphics2D g = bi.createGraphics();
      //x,y轴默认是从0坐标开始
      int x = 0;
      int y = 0;
      //默认两张水印图片的间隔高度是水印图片的1/3
      int temp = icheight/3;
      int space = 1;
      if(height>=icheight){
      space = height/icheight;
      if(space>=2){
      temp = y = icheight/2;
      if(space==1||space==0){
      x = 0;
      y = 0;
      }
      }
      }else{
      x = 0;
      y = 0;
      }
      //设置对线段的锯齿状边缘处理
      g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,RenderingHints.VALUE_INTERPOLATION_BILINEAR);
      //呈现一个图像,在绘制前进行从图像空间到用户空间的转换
      g.drawImage(img.getScaledInstance(width,height,Image.SCALE_SMOOTH),0,0,null);
      for(int i=0;i<space;i++){
      if (null != degree) {
        //设置水印旋转
        g.rotate(Math.toRadians(degree),(double) bi.getWidth() / 2, (double) bi.getHeight() / 2);
      }
      //水印图象的路径 水印一般为gif或者png的,这样可设置透明度
      ImageIcon imgIcon = new ImageIcon(icon);
      //得到Image对象。
      Image con = imgIcon.getImage();
      //透明度,最小值为0,最大值为1
      float clarity = 0.6f;
      g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP,clarity));
      //表示水印图片的坐标位置(x,y)
      //g.drawImage(con, 300, 220, null);
      g.drawImage(con, x, y, null);
      g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
      y+=(icheight+temp);
      }
      g.dispose();
      File sf = new File(output, imageName+"."+imageType);
    ImageIO.write(bi, imageType, sf); // 保存图片
      result = "图片完成添加Icon水印";
    } catch (Exception e) {
      e.printStackTrace();
    }
    return result;
  }
/**
   * 给图片添加单个图片水印、可设置水印图片旋转角度
   * @param icon 水印图片路径(如:F:/images/icon.png)
   * @param source 没有加水印的图片路径(如:F:/images/6.jpg)
   * @param output 加水印后的图片路径(如:F:/images/)
   * @param imageName 图片名称(如:11111)
   * @param imageType 图片类型(如:jpg)
   * @param degree 水印图片旋转角度,为null表示不旋转
   */
  public static String markImageBySingleIcon(String icon,String source,String output,String imageName,String imageType,Integer degree) {
    String result = "添加图片水印出错";
    try {
    File file = new File(source);
    File ficon = new File(icon);
    if (!file.isFile()) {
      return source + " 不是一个图片文件!";
    }
      //将icon加载到内存中
      Image ic = ImageIO.read(ficon);
      //icon高度
      int icheight = ic.getHeight(null);
      //将源图片读到内存中
      Image img = ImageIO.read(file);
      //图片宽
      int width = img.getWidth(null);
      //图片高
      int height = img.getHeight(null);
      BufferedImage bi = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
      //创建一个指定 BufferedImage 的 Graphics2D 对象
      Graphics2D g = bi.createGraphics();
      //x,y轴默认是从0坐标开始
      int x = 0;
      int y = (height/2)-(icheight/2);
      //设置对线段的锯齿状边缘处理
      g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,RenderingHints.VALUE_INTERPOLATION_BILINEAR);
      //呈现一个图像,在绘制前进行从图像空间到用户空间的转换
      g.drawImage(img.getScaledInstance(width,height,Image.SCALE_SMOOTH),0,0,null);
      if (null != degree) {
        //设置水印旋转
        g.rotate(Math.toRadians(degree),(double) bi.getWidth() / 2, (double) bi.getHeight() / 2);
      }
      //水印图象的路径 水印一般为gif或者png的,这样可设置透明度
      ImageIcon imgIcon = new ImageIcon(icon);
      //得到Image对象。
      Image con = imgIcon.getImage();
      //透明度,最小值为0,最大值为1
      float clarity = 0.6f;
      g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP,clarity));
      //表示水印图片的坐标位置(x,y)
      //g.drawImage(con, 300, 220, null);
      g.drawImage(con, x, y, null);
      g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
      g.dispose();
      File sf = new File(output, imageName+"."+imageType);
    ImageIO.write(bi, imageType, sf); // 保存图片
      result = "图片完成添加Icon水印";
    } catch (Exception e) {
      e.printStackTrace();
    }
    return result;
  }
  /**
   * 给图片添加多个文字水印、可设置水印文字旋转角度
   * @param source 需要添加水印的图片路径(如:F:/images/6.jpg)
   * @param outPut 添加水印后图片输出路径(如:F:/images/)
   * @param imageName 图片名称(如:11111)
   * @param imageType 图片类型(如:jpg)
   * @param color 水印文字的颜色
   * @param word 水印文字
   * @param degree 水印文字旋转角度,为null表示不旋转
   */
  public static String markImageByMoreText(String source,String output,String imageName,String imageType,Color color,String word,Integer degree) {
    String result = "添加文字水印出错";
  try {
      //读取原图片信息
      File file = new File(source);
      if (!file.isFile()) {
      return file + " 不是一个图片文件!";
    }
      Image img = ImageIO.read(file);
      //图片宽
      int width = img.getWidth(null);
      //图片高
      int height = img.getHeight(null);
      //文字大小
      int size = 50;
      //加水印
      BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
      Graphics2D g = bi.createGraphics();
      g.drawImage(img, 0, 0, width, height, null);
      //设置水印字体样式
      Font font = new Font("宋体", Font.PLAIN, size);
      //根据图片的背景设置水印颜色
      g.setColor(color);
      int x = width/3;
      int y = size;
      int space = height/size;
      for(int i=0;i<space;i++){
      //如果最后一个坐标的y轴比height高,直接退出
      if((y+size)>height){
      break;
      }
      if (null != degree) {
        //设置水印旋转
        g.rotate(Math.toRadians(degree),(double) bi.getWidth() / 2, (double) bi.getHeight() / 2);
      }
      g.setFont(font);
      //水印位置
      g.drawString(word, x, y);
      y+=(2*size);
      }
      g.dispose();
      //输出图片
      File sf = new File(output, imageName+"."+imageType);
    ImageIO.write(bi, imageType, sf); // 保存图片
      result = "图片完成添加Word水印";
    } catch (Exception e) {
      e.printStackTrace();
    }
  return result;
  }
  /**
   * 给图片添加单个文字水印、可设置水印文字旋转角度
   * @param source 需要添加水印的图片路径(如:F:/images/6.jpg)
   * @param outPut 添加水印后图片输出路径(如:F:/images/)
   * @param imageName 图片名称(如:11111)
   * @param imageType 图片类型(如:jpg)
   * @param color 水印文字的颜色
   * @param word 水印文字
   * @param degree 水印文字旋转角度,为null表示不旋转
   */
  public static String markImageBySingleText(String source,String output,String imageName,String imageType,Color color,String word,Integer degree) {
    String result = "添加文字水印出错";
  try {
      //读取原图片信息
      File file = new File(source);
      if (!file.isFile()) {
      return file + " 不是一个图片文件!";
    }
      Image img = ImageIO.read(file);
      int width = img.getWidth(null);
      int height = img.getHeight(null);
      //加水印
      BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
      Graphics2D g = bi.createGraphics();
      g.drawImage(img, 0, 0, width, height, null);
      //设置水印字体样式
      Font font = new Font("宋体", Font.PLAIN, 50);
      //根据图片的背景设置水印颜色
      g.setColor(color);
      if (null != degree) {
        //设置水印旋转
        g.rotate(Math.toRadians(degree),(double) bi.getWidth() / 2, (double) bi.getHeight() / 2);
      }
      g.setFont(font);
      int x = width/3;
      int y = height/2;
      //水印位置
      g.drawString(word, x, y);
      g.dispose();
      //输出图片
      File sf = new File(output, imageName+"."+imageType);
    ImageIO.write(bi, imageType, sf); // 保存图片
      result = "图片完成添加Word水印";
    } catch (Exception e) {
      e.printStackTrace();
    }
  return result;
  }
  /**
   * 给图片加马赛克
   * @param source 原图片路径(如:F:/images/6.jpg)
   * @param output 打马赛克后,图片保存的路径(如:F:/images/)
   * @param imageName 图片名称(如:11111)
   * @param imageType 图片类型(如:jpg)
   * @param size 马赛克尺寸,即每个矩形的宽高
   * @return
   */
  public static String markImageByMosaic(String source,String output,String imageName,String imageType,int size){
  String result = "图片打马赛克出错";
  try{
    File file = new File(source);
    if (!file.isFile()) {
      return file + " 不是一个图片文件!";
    }
    BufferedImage img = ImageIO.read(file); // 读取该图片
    int width = img.getWidth(null); //原图片宽
      int height = img.getHeight(null); //原图片高
    BufferedImage bi = new BufferedImage(width,height, BufferedImage.TYPE_INT_RGB);
    //马赛克格尺寸太大或太小
    if (width < size || height < size) {
      return "马赛克格尺寸太大";
    }
    if(size<=0){
     return "马赛克格尺寸太小";
    }
    int xcount = 0; //x方向绘制个数
    int ycount = 0; //y方向绘制个数
    if (width % size == 0) {
      xcount = width / size;
    } else {
      xcount = width / size + 1;
    }
    if (height % size == 0) {
      ycount = height / size;
    } else {
      ycount = height / size + 1;
    }
    int x = 0; //x坐标
    int y = 0;
//y坐标
    //绘制马赛克(绘制矩形并填充颜色)
    Graphics2D g = bi.createGraphics();
    for (int i = 0; i < xcount; i++) {
      for (int j = 0; j < ycount; j++) {
        //马赛克矩形格大小
        int mwidth = size;
        int mheight = size;
        if(i==xcount-1){  //横向最后一个不够一个size
          mwidth = width-x;
        }
        if(j == ycount-1){ //纵向最后一个不够一个size
          mheight = height-y;
        }
        //矩形颜色取中心像素点RGB值
        int centerX = x;
        int centerY = y;
        if (mwidth % 2 == 0) {
          centerX += mwidth / 2;
        } else {
          centerX += (mwidth - 1) / 2;
        }
        if (mheight % 2 == 0) {
          centerY += mheight / 2;
        } else {
          centerY += (mheight - 1) / 2;
        }
        Color color = new Color(img.getRGB(centerX, centerY));
        g.setColor(color);
        g.fillRect(x, y, mwidth, mheight);
        y = y + size;// 计算下一个矩形的y坐标
      }
      y = 0;// 还原y坐标
      x = x + size;// 计算x坐标
    }
    g.dispose();
    File sf = new File(output, imageName+"."+imageType);
    ImageIO.write(bi, imageType, sf); // 保存图片
    result = "打马赛克成功";
  }catch(Exception e){
  e.printStackTrace();
  }
    return result;
  }
}

更多java相关内容感兴趣的读者可查看本站专题:《Java图片操作技巧汇总》、《java日期与时间操作技巧汇总》、《Java操作DOM节点技巧总结》、《Java文件与目录操作技巧汇总》及《Java数据结构与算法教程》。

希望本文所述对大家java程序设计有所帮助。

您可能感兴趣的文章:

  • 图片叠加效果Java代码实现
  • java中ImageReader和BufferedImage获取图片尺寸实例
  • java IO流读取图片供前台显示代码分享
  • Java实现的图片高质量缩放类定义与用法示例
  • Java实现的微信图片处理工具类【裁剪,合并,等比例缩放等】
  • Java Servlet上传图片到指定文件夹并显示图片
  • Java实现用Freemarker完美导出word文档(带图片)
  • Java从网络读取图片并保存至本地实例
  • Eclipse中引入com.sun.image.codec.jpeg包报错的完美解决办法
(0)

相关推荐

  • Java Servlet上传图片到指定文件夹并显示图片

    在学习Servlet过程中,针对图片上传做了一个Demo,实现的功能是:在a页面上传图片,点击提交后,将图片保存到服务器指定路径(D:/image):跳转到b页面,b页面读取展示绝对路径(D:/image)的图片.主要步骤如下: 步骤一:上传页面uploadphoto.jsp 需要注意两个问题: 1.form 的method必须是post的,get不能上传文件, 还需要加上enctype="multipart/form-data" 表示提交的数据是二进制文件. 2.需要提供type=&

  • Java从网络读取图片并保存至本地实例

    本文实例为大家分享了Java从网络读取图片并保存至本地的具体代码,供大家参考,具体内容如下 package getUrlPic; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; public cl

  • Java实现的图片高质量缩放类定义与用法示例

    本文实例讲述了Java实现的图片高质量缩放类定义与用法.分享给大家供大家参考,具体如下: 找了很多都不理想,最后找个到老外写的,不得不承认老外写的确实牛B. package com.test; import com.sun.image.codec.jpeg.JPEGImageEncoder; import com.sun.image.codec.jpeg.JPEGCodec; import com.sun.image.codec.jpeg.JPEGEncodeParam; import java

  • 图片叠加效果Java代码实现

    本文实例为大家分享了Java实现图片叠加效果展示的具体代码,供大家参考,具体内容如下 import java.awt.AlphaComposite; import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import javax.imageio.ImageIO; public class NewImageUtils { /*

  • java中ImageReader和BufferedImage获取图片尺寸实例

    ImageReader 对象通常由特定格式的服务提供者接口 (SPI) 类实例化.服务提供者类(例如 ImageReaderSpi 的实例)向 IIORegistry 注册,后者使用前者进行格式识别和表示可用格式 reader 和 writer. BufferedImage子类描述具有可访问图像数据缓冲区的Image.BufferedImage由图像数据的ColorModel和Raster组成.Raster的SampleModel中band的数量和类型必须与ColorModel所要求的数量和类型

  • Java实现的微信图片处理工具类【裁剪,合并,等比例缩放等】

    本文实例讲述了Java实现的微信图片处理工具类.分享给大家供大家参考,具体如下: 现在 外面核心,图片文章比较少,看了拷贝代码,而用不了,用相应jar包处理,很多等比例缩放,达不到 想要的给予的期望:本工具类,是之前做微信打印机写的 基于java自带的类,基于rgb. package com.zjpz.util; import java.awt.Color; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt

  • Java实现用Freemarker完美导出word文档(带图片)

    前言 最近在项目中,因客户要求,将页面内容(如合同协议)导出成word,在网上翻了好多,感觉太乱了,不过最后还是较好解决了这个问题. 准备材料 1.word原件 2.编辑器(推荐Firstobject free XML editor) 实现步骤 1.用Microsoft Office Word打开word原件: 2.把需要动态修改的内容替换成***,如果有图片,尽量选择较小的图片几十K左右,并调整好位置: 3.另存为,选择保存类型Word 2003 XML 文档(*.xml)[这里说一下为什么用

  • java IO流读取图片供前台显示代码分享

    最近项目中需要用到IO流来读取图片以提供前台页面展示,由于以前一直是用url路径的方式进行图片展示,一听说要项目要用IO流读取图片感觉好复杂一样,但任务下达下来了,做为程序员只有选择去执行喽,于是找了点资料看了会api, 嘿感觉挺简单的,由于是第一次采用IO流的方式进行读取图片供页面显示,所以把以下代码记录一下 后台代码: /** * IO流读取图片 by:long * @return */ @RequestMapping(value = "/IoReadImage/{imgName}"

  • Eclipse中引入com.sun.image.codec.jpeg包报错的完美解决办法

    在Eclipse中开发JAVAT程序处理图片时,需要引入两个包: import com.sun.image.codec.jpeg.JPEGCodec; import com.sun.image.codec.jpeg.JPEGImageEncoder; 但有时引入这个两个包时会报出错误: Access restriction: The type JPEGImageEncoder is not accessible due to restriction on required library C:/

  • Java实现给图片添加图片水印,文字水印及马赛克的方法示例

    本文实例讲述了Java实现给图片添加图片水印,文字水印及马赛克的方法.分享给大家供大家参考,具体如下: 可以在eclipse中新建个Utils类,把以下代码复制进去直接使用,以下方法实现单个或多个水印的添加 package com.rzxt.fyx.common.util; import java.awt.AlphaComposite; import java.awt.Color; import java.awt.Font; import java.awt.Graphics2D; import

  • Java如何给Word文档添加多行文字水印

    前言 我在以往的文章中曾介绍过如何给Word文档添加文本水印和图片水印,及怎样删除文档中的水印.关于文本水印,之前那篇教程里主要指的是单行字体的水印,而在操作Word文档时,有时也会碰到需要添加多行文字水印的情况.所以,本文将演示如何使用Java程序来为Word文档添加多行文字水印. 代码测试环境: Intellij Idea2019.1 JDK 1.8.0 Spire.Doc.jar Jar包获取及导入 方法一:手动将Jar包导入IDEA.具体步骤如下: 步骤 1:在 E-iceblue中文官

  • asp .net实现给图片添加图片水印方法示例

    前言 本文主要给大家介绍的是asp .net实现给图片添加图片水印的方法,注意是图片水印,需要的朋友们可以参考学习,下面话不多说来看看详细的介绍吧. 方法如下 首先写好一个写入图片水印的类,先创建一个ImageWriter类库   (该类中有包含枚举类型和方法) using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; using System.Co

  • js给图片打马赛克的方法示例

    本文主要主要介绍了js给图片打马赛克的方法示例,分享给大家,具体如下: 效果演示 Canvas简介 这个 HTML 元素是为了客户端矢量图形而设计的.它自己没有行为,但却把一个绘图 API 展现给客户端 JavaScript 以使脚本能够把想绘制的东西都绘制到一块画布上. HTML5 标签用于绘制图像(通过脚本,通常是 JavaScript) 不过, 元素本身并没有绘制能力(它仅仅是图形的容器) - 您必须使用脚本来完成实际的绘图任务 getContext() 方法可返回一个对象,该对象提供了用

  • 利用Java设置Word文本框中的文字旋转方向的实现方法

    Java设置Word文本框中的文字旋转方向 本次程序测试环境如下: Word测试文档版本:.docx 2013 Word Jar包工具:free spire.doc.jar 3.9.0 代码编译工具:IDEA Jdk版本:1.8.0 导入操作文档所需的jar包工具,如图结果: Java import com.spire.doc.*; import com.spire.doc.documents.*; import com.spire.doc.fields.TextBox; import com.

  • Java 在Excel中添加分离型饼图、环形图的方法

    一.概述 Excel中可支持多种不同类型的图表,本文介绍如何绘制分离型饼图和环形图.其中,分离型饼图的绘制可分为整体分离型(即设置饼图分离程度)和局部分离(即设置点爆炸型值)两种情况.下面将以Java程序代码介绍如何在Excel中实现以上图形. 二.程序环境 Spire.Xls.jar Jdk 1.8.0(版本>=1.6.0即可) IDEA 注:Jar使用的是Free Spire.XLS for Java(免费版)中的Spire.Xls.jar.编辑代码前,导入jar到Java程序,两种方法可导

  • Java数据结构之链表、栈、队列、树的实现方法示例

    本文实例讲述了Java数据结构之链表.栈.队列.树的实现方法.分享给大家供大家参考,具体如下: 最近无意中翻到一本书,闲来无事写几行代码,实现几种常用的数据结构,以备后查. 一.线性表(链表) 1.节点定义 /**链表节点定义 * @author colonel * */ class Node { public int data; Node next=null; public Node(int data){ this.data=data; } } 2.链表操作类 /**链表操作类 * @auth

  • Java实现储存对象并按对象某属性排序的几种方法示例

    本文实例讲述了Java实现储存对象并按对象某属性排序的几种方法.分享给大家供大家参考,具体如下: 在编程的时候,经常会出现对某一种类的对象们按照某属性进行自定义的排序,比如:学生对象按照age大小排序. 有一种方法就是把age单独提出来排好序,然后按照ages数组的顺序把students重存一次.但是这样太繁琐了,有没有更好的方法呢? 有滴~ 第一种,可以实现边添加边排序,需要用到TreeSet. 第二种,用数组存放对象们,但是不需单独取出某属性排列好再重存,而是在原数组上用比较器重新排一次序.

  • Java与Node.js利用AES加密解密出相同结果的方法示例

    前言 工作中遇到nodejs端通过aes加密,安卓客户端Java解密,同样nodejs也需要解密安卓客户端加密过来的内容,发现两个加密结果不一样,查询资料发现java端需要对密钥再MD5加密一遍,以下是Java与Node.js利用AES加密解密出相同结果的方法,需要的朋友们下面来一起学习学习吧. JAVA代码如下: package g.g; import java.security.MessageDigest; import javax.crypto.Cipher; import javax.c

  • Java通过在主循环中判断Boolean来停止线程的方法示例

    本文实例讲述了Java通过在主循环中判断Boolean来停止线程的方法.分享给大家供大家参考,具体如下: package Threads; /** * Created by Frank */ public class StopBoolean extends Thread { // 确保变化对其它线程可见(主要是主线程要可见) protected volatile boolean done = false; public void run() { while (!done) { System.ou

随机推荐