SpringBoot入门
SpringBoot入门 概述 本篇只是对springboot的基本使用的总结,学习视频->Day05-01. 请求响应-概述_哔哩哔哩_bilibili,使用postman进行调试。 请求 此处的请求含义:后端接收来自浏览器端的请求指令,进行解析 简单参数 请求: GET指令:http://localhost:8080/simpleParam?name=miku&age=16 POST指令:http://localhost:8080/simpleParam请求体:name=Miku&age=16 Java代码: 原始方式: 12345678910//在原始的Web程序中,获取请求参数,需要通过HttpServletRequest对象手动获取@RequestMapping("/simpleParam")public String simpleRequest(HttpServletRequest request) { String name = request.getParameter("name");//需要与请求参数的key保持一致 String ageStr = request.getParameter("age");//需要与请求参数的key保持一致 int age = Integer.parseInt(ageStr); System.out.println("Name: " + name + ", Age: " + age); return "OK";}//繁琐,并且需要进行手动类型转换 SpringBoot方式: 简单参数,参数名与形参列表名相同,定义形参即可接收参数 12345@RequestMapping("/simpleParam")public String simpleRequest(int age,String name) { System.out.println(name + ":" + age); return "OK";} 如果形参名和请求参数名不一致,可以使用@RequestParam进行映射 12345@RequestMapping("/simpleParam")public String simpleRequest(int age,@RequestParam(name="name",required = true) String username) { System.out.println(username + ":" + age); return "OK";} 注解@RequestParam中有两个属性,一个是重定向,一个是required属性,第二个参数如果不写默认为true,即参数是必须的,如果缺少该参数会报400的状态码,表明客户端请求错误。 实体参数 简单实体对象,请求参数名与形参对象属性名相同,定义POJO接收即可 请求:http://localhost:8080/simplePojo?name=miku&age=16 12345@RequestMapping("/simplePojo")public String simpleRequest(User user) { System.out.println(user); return "OK";} 需要创建User对象,声明相应属性、getset方法、toString方法 复杂实体对象,请求参数名与形参对象属性名相同,按照对象层次结构关系即可接收嵌套POJO属性参数 请求:http://localhost:8080/complexPojoname=miku&age=16&address.city=Tokyo&address.country=Japan 12345@RequestMapping("/complexPojo")public String simpleRequest(User1 user) { System.out.println(user); return...
JavaSE-网络编程
网络编程 软件架构: CS架构:客户端-服务器 BS架构:浏览器-服务器 不过现在的很多软件都是一种混合开发,就是将CS架构和BS架构融合起来。 网络编程三要素 如何准确定位一台或多态主机:使用IP地址 如何定位主机上的特定的应用:使用端口号 如何可靠、高效地进行数据传输:规范通信协议 IP地址 IP地址:网络中的一台计算机设备做唯一编号 IP地址分类: 分类方式一: IPv4:占用4个字节,表示为a.b.c.d的形式,以点分十进制表示 IPv6:占用16个字节 分类方式二: 公网地址(万维网使用)和私网地址(局域网使用)192.168.开头的就是私有地址 本地回路地址:127.0.0.1 域名:便捷地记录ip地址 www.baidu.com kuoz.top 域名使用中通过DNS解析成IP再进行访问的 端口号 端口号可以唯一标识主机中的进程 不同的进程分配不同的端口号 范围:0~65535 网络通信协议 OSI模型:过于理想化,没能实现 TCP/IP:分为应用层、传输层、网络层、物理+数据链路层 InetAddress类 InetAddress类的一个实例就代表一个具体的ip地址 实例化方式: InetAddress getByName(String host) InetAddress getLocalHost() TCP协议和UDP协议 计算机网络的重要重要指示,在此处简要了解。 TCP的Socket网络编程 网络上具有唯一标识的IP地址和端口号的组合,唯一可识别的标识符套接字(Socket) 1234567891011121314151617181920212223242526272829303132333435363738394041@Testpublic void client() throws IOException { //创建Socket实例 int port = 8888; InetAddress address = InetAddress.getByName("10.10.208.62"); Socket socket = new Socket(address, port); //通过Socket创建输出流 OutputStream os = socket.getOutputStream(); //发送数据 os.write("嗨嗨嗨, 服务器我来辣!".getBytes()); //关闭Socket及相关流 os.close(); socket.close();}@Testpublic void server() throws IOException { //创建serverSocket实例 int port = 8888; ServerSocket serverSocket = new ServerSocket(port); //接收来自于客户端的Socket Socket socket = serverSocket.accept(); System.out.println("客户端连接成功,等待接收数据..."); System.out.println("收到了来自"+socket.getInetAddress().getHostAddress()+"的连接"); //通过Socket创建输入流 InputStream is = socket.getInputStream(); //读写过程 byte[] buffer = new byte[5]; ByteArrayOutputStream baos = new ByteArrayOutputStream(); int len; while((len = is.read(buffer)) != -1) { //当byte太小时,这里中文会因为中间被截断而出乱码,通过baos来解决 //String message = new String(buffer, 0, len); //解决方法 baos.write(buffer, 0, len); } System.out.print(baos.toString()); System.out.print("\n接收完毕"); //关闭Socket和相关流 is.close(); ...
Maven
Maven 概述 Maven是一款管理和构建Java项目的工具。基于POM(项目对象模型)的概念,通过一小段描述来管理项目 Maven坐标,唯一标识和定位一个项目 groupId:组织 artifactId:模块名称 version:版本 仓库:用于存储资源,管理jar包 本地仓库:自己计算机上的一个目录 中央仓库:由Maven团队维护的全球唯一的仓库 远程仓库:一般由公司团队搭建的私有仓库 使用顺序:本地仓库>远程仓库>中央仓库 依赖管理 依赖:指当前项目运行所需的jar包 配置依赖(在IDEA中) 在pom.xml中编写标签 在标签中使用引入坐标 定义坐标的groupId,artifactId,version 点击刷新按钮,引入最新加入的坐标 12345678<dependencyies> <dependency> <groupId></groupId> <artifactId></artifactId> <version></version> </dependency> ...</dependencyies> 依赖传递 依赖具有传递性 直接依赖:在当前项目中通过依赖配置建立的关系 间接依赖:被依赖的资源如果依赖其他资源,当前项目间接依赖其他资源 排除依赖:主动断开依赖的资源,被排除的资源无需指定版本 123456<exclusions> <exclusion> <groupId></groupId> <artifactId></artifactId> </exclusion></exclusions> 依赖范围 scope值 主程序 测试程序 打包(运行) 范例 compile(默认) Y Y Y log4j test - Y - junit provided Y Y - servlet-api runtime - Y Y jdbc驱动 可以通过下面的xml标签来设置依赖范围 1<scope>...</scope> 生命周期 每套生命周期包含一些阶段(phase),阶段是有顺序的,后面的阶段依赖于前面的阶段。(运行后面的阶段,前面的阶段也会运行) 生命周期阶段(常见) 常见生命周期阶段 clean 移除上一次构建生成的文件 compile 编译项目源代码 test 使用合适的单元测试框架运行测试 package 将编译后的文件打包,如:jar、war等 install 安装项目到本地仓库
MySQL
MySQL-基础 数据库管理系统DBMS MySQL数据模型 客户端->DBMS->多个数据库->多个二维表 SQL语句 DDL(Data Definition Language)数据定义语言(数据库、表、字段) DML(Data Manipulation Language)数据操作语言 DQL(Data Query Language)数据查询语言 DCL(Data Control Language)数据控制语言,管理数据库用户,控制数据库的访问权限 DDL-数据定义 数据库操作 大类 语句 作用 查询 show databases 查询所有数据库 seclect database() 查询当前数据库 创建 create database [if not exists] 数据库名 (如果不存在)创建一个数据库 使用 use 数据库名; 使用数据库 删除 drop database [if exists] 数据库名 删除数据库 表操作-查询 语句 作用 show tables; 查询当前数据库所有表 desc 表名; 查询表结构 show create table 表名; 查询指定表的建表语句 表操作-创建 12345create table 表名( 字段1 字段类型 [约束] [comment 字段1注释], …… 字段n 字段类型 [约束] [comment 字段1注释])[comment 表注释]; 关于约束: 约束 描述 关键字 非空约束 限制字段值不能为null not null 唯一约束 保证字段所有数据唯一 unique 主键约束 主键是一行数据的唯一标识,非空且唯一 primary key 默认约束 字段未指定值则用默认值 default 外键约束 让两张表的数据建立连接 foreign key 字段数据类型 数值 类型 大小(byte) 描述 tinyint 1 小整数值 smallint 2 大整数值 mediumint 3 大整数值 int 4 大整数值 bigint 8 极大整数值 float 4 单精度浮点数 double 8 双精度浮点数 decimal 小数值(精确定点数) 例如double,需使用double(整个数的长度,小数部分长度) 字符串 类型 描述 char 定长字符串 varchar 变长字符串 tinyblob 不超过255个字符的二进制数据 tinytext 短文本字符串 blob 二进制形式的长文本数据 text 长文本数据 midiumblob 二进制形式的中等长度文本数据 midiumtext 中等长度文本数据 longblob 二进制形式的极大文本数据 longtext 极大文本数据 日期时间 大小 范围 格式 描述 date 3 1000-01-01至9999-12-31 YYYY-MM-DD 日期值 time 3 -838:59:59至838:59:59 HH:MM:SS 时间值或持续时间 year 1 1901至2155 YYYY 年份值 datatime 8 1000-01-01 00:00:00至9999-12-31 23:59:59 YYYY-MM-DD HH:MM:SS 混合日期和时间值 timestamp 4 1970-01-01 00:00:01至2038-01-19 03:14:07 YYYY-MM-DD HH:MM:SS 混合日期和时间值,时间戳 修改、删除表结构 语言可以不掌握,但是要会图形化操作 DML-数据操作 添加数据: insert into 表名(字段1,字段2,……) values(值1,值2,……); 字符串应该和日期型数据应该包含在引号内 插入的数据大小,应该在字段的规定范围内 修改数据 update 表名 set 字段名1=值1,字段名2=值2,…[where 条件] 删除数据 delete from 表名 [where 条件] DQL-数据查询 基本查询: 基本查询 select 字段列表 from 表名; select * from 表名;(不建议在开发中使用这种方式,因为不直观) 起别名 select 字段 as ‘别名’ from 表名;as可省略 去重 select distinct 字段名称 from 表名; 条件查询: select 字段列表 from 表名 where 条件列表; 比较运算符 功能 > >=...
JavaSE-Java8的两个重要特性
jdk8 新特性 函数式接口: 函数式接口是什么?如果接口中只声明有一个抽象方法,则此接口成为函数式接口(FunctionalInterface) 为什么要有函数式接口?因为只有给函数式接口创建对象时,才可以使用lambda表达式。 java8中声明的函数式接口所在包:java.util.function 4个基本的函数式接口:(直接copy宋的课件) 函数式接口 称谓 参数类型 用途 Consumer<T> 消费型接口 T 对类型为T的对象应用操作,包含方法: void accept(T t) Supplier<T> 供给型接口 无 返回类型为T的对象,包含方法:T get() Function<T, R> 函数型接口 T 对类型为T的对象应用操作,并返回结果。结果是R类型的对象。包含方法:R apply(T t) Predicate<T> 判断型接口 T 确定类型为T的对象是否满足某约束,并返回 boolean 值。包含方法:boolean test(T t) lambda表达式 lambda表达式怎么用? 语法规则: ->的左边:lambda的形参列表,参数的类型都可以省略。如果形参列表只有一个,则一对()也可以省略。 ->的右边:lambda体,只有一行执行语句时,则一对{}可以省略,如果有return,则也要省略。 写法举例 1Comparator<Integer> com = (o1 , o2) -> Integer.compara(o1,o2); lambda表达式的本质: 一方面,lambda表达式作为接口实现类的对象;另一方面,lambda表达式是匿名函数。 方法引用 方法引用可以看作是lambda表达式的进一步刻画。 当需要提供一个函数式接口的实例时,我们可以使用lambda表达式提供此实例。 当满足一定的条件是,我们还可以使用方法引用或构造器引用替换lambda表达式。 方法引用作为了函数式接口的实例。 格式: 对象 :: 实例方法 要求:函数式接口的抽象方法a与其内部实现时调用的对象的某个方法b的形参列表和返回值类型都相同。此时可以考虑使用方法b实现对a的替换、覆盖。 注意此方法b是非静态方法,需要对象调用。 类 :: 静态方法 要求:函数式接口的抽象方法a与其内部实现时调用的对象的某个静态方法b的形参列表和返回值类型都相同。此时可以考虑使用方法b实现对a的替换、覆盖。 注意此方法b是静态方法,需要类调用。 类 :: 实例方法 要求:函数式接口中的抽象方法a与其内部实现时调用的对象的某个方法b的形参列表和返回值类型都相同。同时,抽象方法a中有n个参数,方法b中有n-1个参数,且抽象方法a的第一个参数作为方法b的调用者,且抽象方法a的后n-1个参数与方法b的n-1个参数的类型相同(或一致)。 注意此方法b是非静态方法,需要对象调用。但是形式上,写出对象a所属的类。 构造器引用 格式:类名 :: new 调用了类名对应的类中某一个确定的构造器。具体调用的是类中的哪一个构造器,取决于函数式接口的抽象方法的形参列表。 数组引用 格式:数组名 :: new StreamAPI Stream使用的流程 实例化 一系列的中间操作 执行终止操作 实例化: 三种方法: 方法一:通过集合 例如:对于List结构,直接使用list.stream()就能创建stream实例 方法二:通过数组 类似方法一,使用Arrays的静态方法stream()Arrays.stream(arr) 方法三:streamof public static<T> Stream<T> of(T... values) : 返回一个流 例如: 12Stream<Integer> stream = Stream.of(1,2,3,4,5);stream.forEach(System.out::println); 中间操作: 筛选与切片 123456789101112131415@Testpublic void test1() { //创建Stream List<Employee> list = EmployeeData.empData(); Stream<Employee> stream = list.stream(); //filter(Predicate p) 过滤 stream.filter(e -> e.getAge() >...
JavaSE-File类与IO流
File类与IO流 File类的实例化 File类位于java.io包下,本章中涉及到的相关流也都声明在java.io包下。 File类的一个对象,对应于操作系统下的一个文件或文件目录(或文件夹) 123456 /*相对路径:相对于某一个文件目录来讲的相对位置。在IDEA中 * 在IDEA中,如果使用单元测试方法,相对路径是相对于当前的module * 如果使用main方法,相对路径是相对于当前的project * */ File file1 = new File("d:/io/test.txt");File file2 = new File("iotest"); 12345678//public File(String parent, String child)//参数1:一定是一个文件目录//参数2:文件目录或者是一个文件 File file1 = new File("d:/io", "test.txt"); //public File(File parent, String child)//参数1:一定是一个文件目录//参数2:文件目录或者是一个文件 File file2 = new File(file1,"file3.txt"); IO流 流(Stream)的分类: 流向不同:输入流、输出流 处理单位不同:字符流、字节流 角色不同:节点流、处理流 (抽象基类) 输入流 输出流 字节流 InputStream OutputStream 字符流 Reader Writer FIleReader、FileWriter: 步骤: 创建读写的File对象 创建输入流或输出流 具体读入或写出 读入:read(char[] cbuffer) 写出:write(String str)/write(char[] cbuffer,0,len) 关闭流资源,防止内存泄露 使用举例:复制hello.txt文件到hello_copy.txt 123456789101112131415161718192021222324252627282930313233@Testpublic void test2(){ FileReader fr = null; FileWriter fw = null; try { File file = new File("hello.txt"); File dest = new File("hello_copy.txt"); fr = new FileReader(file); fw = new FileWriter(dest); char[] cbuffer = new char[5]; int len;//记录每次读入字符个数 while ((len = fr.read(cbuffer)) != -1) { fw.write(cbuffer, 0, len); } } catch (IOException e) { e.printStackTrace(); } finally { //关闭流资源 try { if(fr != null) fr.close(); } catch (Exception e) { e.printStackTrace(); } try { if(fw != null) fw.close(); } catch (Exception e) { e.printStackTrace(); } ...
JavaSE-泛型
泛型 泛型在集合、比较器中的使用 1234567891011121314151617181920212223//泛型在List中的使用@Testpublic void test1(){ //举例:将学生成绩保存在ArrayList中 //标准写法: //ArrayList<Integer> list = new ArrayList<Integer>(); //jdk7的新特性:类型推断 ArrayList<Integer> list = new ArrayList<>(); list.add(56); //自动装箱 list.add(76); list.add(88); list.add(89); //当添加非Integer类型数据时,编译不通过 //list.add("Tom");//编译报错 Iterator<Integer> iterator = list.iterator(); while(iterator.hasNext()){ //不需要强转,直接可以获取添加时的元素的数据类型 Integer score = iterator.next(); System.out.println(score); }} 123456789101112131415161718192021222324252627282930313233343536//泛型在Map中的使用@Testpublic void test2(){ HashMap<String,Integer> map = new HashMap<>(); map.put("Tom",67); map.put("Jim",56); map.put("Rose",88); //编译不通过 // map.put(67,"Jack"); //遍历key集 Set<String> keySet = map.keySet(); for(String str:keySet){ System.out.println(str); } //遍历value集 Collection<Integer> values = map.values(); Iterator<Integer> iterator = values.iterator(); while(iterator.hasNext()){ Integer value = iterator.next(); System.out.println(value); } //遍历entry集 Set<Map.Entry<String, Integer>> entrySet = map.entrySet(); Iterator<Map.Entry<String, Integer>> iterator1 = entrySet.iterator(); while(iterator1.hasNext()){ Map.Entry<String, Integer> entry = iterator1.next(); String key = entry.getKey(); Integer value = entry.getValue(); System.out.println(key + ":" + value); }} 1234567891011121314151617181920class CircleComparator1 implements Comparator<Circle> { @Override public int compare(Circle o1, Circle o2) { //不再需要强制类型转换,代码更简洁 return Double.compare(o1.getRadius(),...
JavaSE-集合框架
集合框架 Java集合框架体系 java.util.Collection:存储一个一个的数据 子接口:List:存储有序、可重复的数据(“动态”数组) ArrayList(主要实现类)、LinkedList、Vector 子接口:Set:存储无序、不可重复的数据(中学数学中的集合) HashSet(主要实现类)、LinkedHashSet、TreeSet java.util.Map:存储一对一对的数据(key-value键值对,类似于中学数学的函数) HashMap(主要实现类)、LinkedHashMap、TreeMap、Hashtable、Properties Collection接口 常用方法 Collection中有15个常用的方法,其实现类可以使用 集合和数组的转换 集合–>数组toArray 数组–>集合调用Arrays的静态方法asList 向Collection中添加元素的要求:元素所属类一定要重写equals方法 因为Collection的相关方法(contains、remove)在使用时要调用equals方法 遍历 iterator迭代器: iterator迭代器常用来遍历集合元素 123while(iterator.hasNext()){ System.out.println(iterator.next());//next()指针下移,将下移以后的元素返回} (补充)增强for循环: 作用:遍历数组和集合 格式: 123for(要遍历的集合或数组的元素类型 临时变量 : 要遍历的集合或数组变量){ 操作临时变量输出} 说明: 针对于集合来讲,增强for循环底层仍使用的是迭代器 增强for循环执行的过程中,是将集合或数组中的元素依次赋值给临时变量,注意,循环体中对临时变量的修改,可能不会导致原有集合或数组元素的修改 List接口 常用方法 第一部分: Collection中声明的15个方法 第二部分:因为LIst是有序的,所以会增加一些索引方法 常用方法大致可分为:增、删、改、查、插、长度、遍历 方法声明 说明 add(Object ele) 添加ele元素 addAll(Collection eles) 将eles中的所有元素添加进来 remove(Object ele) 删除指定索引的元素,并返回此元素 remove(int index) 删除指定索引的元素,并返回此元素 set(int index , Object ele) 设置指定索引位置的元素为ele get(int index) 获取指定索引元素 add(int index , Object ele) 在指定索引插入ele元素 addAll(int index , Collection...
JavaSE-常用类与基础API
常用类与基础API String类的深入认识 类的声明 123public final class String implements java.io.Serializable, Comparable<String>, CharSequence, Constable, ConstantDesc final:String是不可继承的 Serializable:可序列化的接口。凡是实现此接口的类的对象就可以通过网络或本地流进行数据的传输 comparable:凡是实现此接口的类,其对象都可以比较大小 内部声明的属性 jdk8及之前:private final char value[];//存储字符串的容器 final:指明此value数组一旦初始化,其地址就不可变 jdk9开始,为节省内存空间做了优化:private final byte value[]//存储字符串的容器 字符串常量的存储位置 字符串常量都存储在字符串常量池(StringTable)中 字符串常量池不允许存储两个相同的常量 内存上,jdk7之前存放在方法区,jdk7之后存放在堆空间 String的不可变性 当对字符串进行重新赋值时,需要重新指定一个字符串常量的位置进行赋值,不能在原有的位置修改 当对现有的字符串进行拼接时,需要重新开辟空间以保存拼接以后的字符串,不能在原有位置修改 当调用字符串的replace()替换现有的某个字符时,需要重新开辟空间保存修改以后的字符串,不能在原有位置修改 String实例化的两种方式 第一种:String s1 = "hello" 第二种:String s2 = new String("hello") 连接符: 常量+常量,存储在字符串常量池,返回字面量的地址。注:此时的常量可能是字面量,也可能是final修饰的常量 常量+变量或者变量+变量,通过new创建一个新的字符串,返回堆空间中此字符串对象的地址 调用字符串的intern()返回的是字符串常量池中字面量的地址 concat():不管是常量还是变量,都返回一个新new的对象 String类构造器 12345678910111213// 无参构造(但实际无意义,因为 String 是不可变的)public String();// 通过字符串字面量构造(实际很少直接使用)public String(String original);// 通过字节数组构造(使用平台默认字符集解码)public String(byte[] bytes);// 通过字节数组构造(指定字符集解码)public String(byte[] bytes, String charsetName);// 通过字节数组的指定范围构造(offset 起始位置,length 长度)public String(byte[] bytes, int offset, int length);// 通过字符数组构造public String(char[] value);public String(char[] value, int offset, int count); Stirng类与常见的其它结构之间的转换 Stirng和基本数据类型之间的转换在包装类中已经写过,在此省略 String和char[]的转换 String–>char[]:调用toCharArray(),char[] arr = str.toCharArray() char[]–>String:调用String的构造器 String和byte[]的转换 编码:String–>byte[]:调用getBytes(),()内可以用"字符集名称"指明字符集,不写则使用默认字符集 关于字符集:utf-8中汉字占3个字节,一个字母使用1个字节;gbk中一个汉字占2个字节,一个字母占1个字节。两者都向下兼容ascii码。 解码:byte[]–>String:使用构造器,如果需要也要指定字符集 编码和解码指定字符集要相同,否则会乱码。 String常用的方法 String类包含有查找、截取、字符/字符数组、开头结尾、替换等常用API,内容很多且很啰嗦,建议在使用中学习,在此省略。 StringBuffer和StringBuilder类 对比: String:不可变的字符序列; StringBuffer:可变的字符序列;线程安全,效率低 StringBuilder:可变的字符序列;线程不安全,效率高 理解 声明的内部属性: char[] value 存储的字符序列 int count...
JavaSE-多线程
多线程 概念 程序:为完成任务,用某种语言编写的一组指令的集合。 进程:程序的一次执行过程,或是正在内存中运行的应用程序。 线程:进程可以进一步细化为线程,是程序内部的一条执行路径。线程是CPU调度和执行的最小单位。 不同进程之间是不共享内存的。 进程之间的数据交换和通信的成本很高。 线程调度策略 分时调度:所有线程轮流使用CPU的使用权。并且平均分配每个线程占用CPU的时间 抢占式调度:让优先级高的线程以较大的概率优先使用CPU。如果线程的优先级相同,那么就会随机选一个。Java使用的是抢占式调度。 了解并行和并发 多线程的优点 提供应用程序的响应。 提高计算机CPU的利用率。 改善程序结构。将既长又复杂的进程拆为多个线程,独立运行,便于理解和修改。 多线程创建方式 方式一:继承Thread类的方式 创建一个继承于Thread类的子类 重写Thread类的run() 创建当前Thread的子类对象 通过对象调用start() 创建线程代码: 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950public class ThreadTest { public static void main(String[] args) { //方式1:创建子类 MyThread myThread = new MyThread(); myThread.start(); MyThread2 myThread2 = new MyThread2(); myThread2.start(); //方式2:创建匿名子类 new Thread(){ @Override public void run() { for (int i = 0; i < 100; i++) { if(i%2==0){ System.out.println(Thread.currentThread().getName()+" "+i); } } } }.start(); new Thread(){ @Override public void run() { for (int i = 0; i < 100; i++) { if(i%2!=0){ System.out.println(Thread.currentThread().getName()+" "+i); } } } }.start(); }}class MyThread extends Thread{ @Override public void run() { for (int i = 0; i < 100; i++) { if(i%2==0){ System.out.println(Thread.currentThread().getName()+" "+i); } } }}class MyThread2 extends Thread{ @Override public void run() { for (int i = 0; i < 100; i++) { if(i%2!=0){ ...